Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "tcp.h"
- namespace tcp
- {
- sock create_socket()
- {
- return sock( socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) );
- }
- sock create_socket_connect( char *addr, uint16_t port )
- {
- sockaddr_in name = {0};
- SOCKET s;
- int r;
- name.sin_addr.s_addr = inet_addr(addr);
- name.sin_family = AF_INET;
- name.sin_port = htons(port);
- s = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
- assert( s != SOCKET_ERROR );
- r = ::connect( s, (sockaddr *)&name, sizeof(name) );
- assert( r != SOCKET_ERROR );
- return sock(s);
- }
- sock::sock( SOCKET s )
- {
- this->s = s;
- this->on_recv = nullptr;
- }
- sock::sock()
- {
- this->s = SOCKET_ERROR;
- this->on_recv = nullptr;
- }
- void recv_loop_spawn( sock *s )
- {
- std::thread( [] (sock sk) {
- sk.recv_loop();
- }, *s).detach();
- }
- void sock::recv_loop()
- {
- int r;
- char buff[1536];
- for (;;) {
- if ( this->on_recv ) {
- r = recv( this->s, buff, sizeof(buff), NULL );
- if ( r == 0 ) { // close connection
- this->on_recv( this, nullptr, r, status::CLOSE );
- return;
- } else if ( r == -1 ) { // error.
- this->on_recv( this, nullptr, r, status::FAIL );
- return;
- } else { // data
- this->on_recv( this, (uint8_t *)buff, r, status::OK );
- }
- }
- }
- }
- status sock::connect( char *addr, uint16_t port, void (*on_connect)(sock *_this, status st) )
- {
- sock sk = create_socket_connect( addr, port );;
- if ( on_connect )
- on_connect( &sk, status::OK );
- recv_loop_spawn(&sk);
- return status::OK;
- }
- status sock::send( uint8_t *buffer, uint32_t buffer_len, void (*on_sent)(sock *_this, status st) )
- {
- std::thread( [buffer, buffer_len, on_sent] (sock *__this, SOCKET s) {
- int r = ::send( s, (const char *)buffer, buffer_len, NULL );
- if ( on_sent )
- on_sent(__this, r != SOCKET_ERROR ? status::OK : status::FAIL );
- }, this, this->s).detach();
- return status::OK;
- }
- status server::listen( char *address, uint16_t port, void (*on_accept)(sock *_this, status st) )
- {
- int r;
- SOCKET s;
- sockaddr_in name;
- s = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
- assert( s != SOCKET_ERROR );
- memset( &name, 0, sizeof(name) );
- name.sin_addr.s_addr = inet_addr( address );
- name.sin_port = htons(port);
- name.sin_family = AF_INET;
- r = bind( s, (sockaddr *)&name, sizeof(name) );
- assert( r != SOCKET_ERROR );
- r = ::listen( s, 64 );
- assert( r != SOCKET_ERROR );
- std::thread( [s, on_accept] () {
- int namelen;
- sockaddr_in name;
- SOCKET con;
- sock sk;
- for (;;) {
- namelen = sizeof(name);
- con = accept( s, (sockaddr *)&name, &namelen );
- assert( con != SOCKET_ERROR );
- sk = sock( con );
- on_accept( &sk, status::OK );
- recv_loop_spawn(&sk);
- }
- }).detach();
- return status::OK;
- }
- };
Add Comment
Please, Sign In to add comment