// // [[DHCP SIP4]] object definition // static tsk_object_t* tnet_dhcp_option_sip_ctor(tsk_object_t * self, va_list * app) { tnet_dhcp_option_sip_t *option = self; if(option){ const void* payload = va_arg(*app, const void*); tsk_size_t payload_size = va_arg(*app, tsk_size_t); const uint8_t* payloadPtr = (const uint8_t*)payload; const uint8_t* payloadEnd = (payloadPtr + payload_size); /* init base */ tnet_dhcp_option_init(TNET_DHCP_OPTION(option), dhcp_code_SIP_Servers_DHCP_Option); option->servers = tsk_list_create(); /* Set values as per RFC 3361. */ if(*payloadPtr == 0){ /* enc=0 */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ |120|27 | 0 | 7 |'e'|'x'|'a'|'m'|'p'|'l'|'e'| 3 |'c'|'o'|'m'| 0 | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+---+---+---+---+ | 7 |'e'|'x'|'a'|'m'|'p'|'l'|'e'| 3 |'n'|'e'|'t'| 0 | +---+---+--- +---+---+---+---+---+---+---+---+---+---+ */ tsk_size_t offset = 1; char* server = 0; payloadPtr++; while((payloadPtr < payloadEnd) && !tnet_dns_rr_qname_deserialize(payload, &server, &offset)){ tsk_string_t* string = tsk_string_create(server); tsk_list_push_back_data(option->servers, (void*)&string); TSK_FREE(server); payloadPtr += offset; } } else{ /* Code Len enc Address 1 Address 2 +-----+-----+-----+-----+-----+-----+-----+-----+-- | 120 | n | 1 | a1 | a2 | a3 | a4 | a1 | ... +-----+-----+-----+-----+-----+-----+-----+-----+-- */ uint32_t address; tsk_string_t* addrstring; char* ip4 = 0; while(payloadPtr < payloadEnd){ ++payloadPtr; address = tnet_htonl_2(payloadPtr); tsk_sprintf(&ip4, "%u.%u.%u.%u", (address>>24)&0xFF, (address>>16)&0xFF, (address>>8)&0xFF, (address>>0)&0xFF); addrstring = tsk_string_create(ip4); tsk_list_push_back_data(option->servers, (void*)&addrstring); TSK_FREE(ip4); payloadPtr+= 4; } } } return self; }
/*=== Main thread */ void *tnet_transport_mainthread(void *param) { tnet_transport_t *transport = param; transport_context_t *context = transport->context; int ret; tsk_size_t i; tsk_bool_t is_stream; tnet_fd_t fd; struct sockaddr_storage remote_addr = {0}; transport_socket_xt* active_socket; /* check whether the transport is already prepared */ if(!transport->prepared){ TSK_DEBUG_ERROR("Transport must be prepared before strating."); goto bail; } is_stream = TNET_SOCKET_TYPE_IS_STREAM(transport->master->type); TSK_DEBUG_INFO("Starting [%s] server with IP {%s} on port {%d} using fd {%d} with type {%d}...", transport->description, transport->master->ip, transport->master->port, transport->master->fd, transport->master->type); while(TSK_RUNNABLE(transport)->running || TSK_RUNNABLE(transport)->started){ if((ret = tnet_poll(context->ufds, context->count, -1)) < 0){ TNET_PRINT_LAST_ERROR("poll have failed."); goto bail; } if(!TSK_RUNNABLE(transport)->running && !TSK_RUNNABLE(transport)->started){ TSK_DEBUG_INFO("Stopping [%s] server with IP {%s} on port {%d} with type {%d}...", transport->description, transport->master->ip, transport->master->port, transport->master->type); goto bail; } /* lock context */ tsk_safeobj_lock(context); /* == == */ for(i=0; i<context->count; i++) { if(!context->ufds[i].revents){ continue; } // TSK_DEBUG_INFO("REVENTS(i=%d) = %d", i, context->ufds[i].revents); if(context->ufds[i].fd == context->pipeR){ TSK_DEBUG_INFO("PipeR event = %d", context->ufds[i].revents); if(context->ufds[i].revents & TNET_POLLIN){ static char __buffer[1024]; if(read(context->pipeR, __buffer, sizeof(__buffer)) < 0){ TNET_PRINT_LAST_ERROR("Failed to read from the Pipe"); } } else if(context->ufds[i].revents & TNET_POLLHUP){ TNET_PRINT_LAST_ERROR("Pipe Error"); goto bail; } context->ufds[i].revents = 0; continue; } /* Get active event and socket */ active_socket = context->sockets[i]; /*================== TNET_POLLHUP ==================*/ if(context->ufds[i].revents & (TNET_POLLHUP)){ fd = active_socket->fd; TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLHUP(%d)", transport->description, fd); #if defined(ANDROID) /* FIXME */ #else tnet_transport_remove_socket(transport, &active_socket->fd); TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, fd); continue; #endif } /*================== TNET_POLLERR ==================*/ if(context->ufds[i].revents & (TNET_POLLERR)){ fd = active_socket->fd; TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLERR(%d)", transport->description, fd); tnet_transport_remove_socket(transport, &active_socket->fd); TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, fd); continue; } /*================== TNET_POLLNVAL ==================*/ if(context->ufds[i].revents & (TNET_POLLNVAL)){ fd = active_socket->fd; TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLNVAL(%d)", transport->description, fd); tnet_transport_remove_socket(transport, &active_socket->fd); TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, fd); continue; } /*================== POLLIN ==================*/ if(context->ufds[i].revents & TNET_POLLIN) { tsk_size_t len = 0; void* buffer = tsk_null; tnet_transport_event_t* e; // TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLIN(%d)", transport->description, active_socket->fd); /* check whether the socket is paused or not */ if(active_socket->paused){ TSK_DEBUG_INFO("Socket is paused"); goto TNET_POLLIN_DONE; } /* Retrieve the amount of pending data. * IMPORTANT: If you are using Symbian please update your SDK to the latest build (August 2009) to have 'FIONREAD'. * This apply whatever you are using the 3rd or 5th edition. * Download link: http://wiki.forum.nokia.com/index.php/Open_C/C%2B%2B_Release_History */ if((tnet_ioctlt(active_socket->fd, FIONREAD, &len) < 0 || !len) && is_stream){ /* It's probably an incoming connection --> try to accept() it */ int listening = 0, remove_socket = 0; socklen_t socklen = sizeof(listening); TSK_DEBUG_INFO("ioctlt(%d), len=%u returned zero or failed", active_socket->fd, len); // check if socket is listening if(getsockopt(active_socket->fd, SOL_SOCKET, SO_ACCEPTCONN, &listening, &socklen) != 0){ #if defined(BSD) /* old FreeBSD versions (and OSX up to Lion) do not support SO_ACCEPTCONN */ listening = 1; #else TNET_PRINT_LAST_ERROR("getsockopt(SO_ACCEPTCONN, %d) failed\n", active_socket->fd); /* not socket accepted -> no socket to remove */ goto TNET_POLLIN_DONE; #endif } if (listening){ if((fd = accept(active_socket->fd, tsk_null, 0)) != TNET_INVALID_SOCKET){ TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_ACCEPT(fd=%d)", transport->description, fd); addSocket(fd, transport->master->type, transport, tsk_true, tsk_false); TSK_RUNNABLE_ENQUEUE(transport, event_accepted, transport->callback_data, fd); if(active_socket->tlshandle){ transport_socket_xt* tls_socket; if((tls_socket = getSocket(context, fd))){ if(tnet_tls_socket_accept(tls_socket->tlshandle) != 0){ TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, fd); tnet_transport_remove_socket(transport, &fd); TNET_PRINT_LAST_ERROR("SSL_accept() failed"); continue; } } } } else{ TNET_PRINT_LAST_ERROR("accept(%d) failed", active_socket->fd); remove_socket = 1; } } else{ TSK_DEBUG_INFO("Closing socket with fd = %d because ioctlt() returned zero or failed", active_socket->fd); remove_socket = 1; } if(remove_socket){ fd = active_socket->fd; tnet_transport_remove_socket(transport, &active_socket->fd); TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, fd); continue; } goto TNET_POLLIN_DONE; } if(len <= 0){ context->ufds[i].revents &= ~TNET_POLLIN; goto TNET_POLLIN_DONE; } if(!(buffer = tsk_calloc(len, sizeof(uint8_t)))){ TSK_DEBUG_ERROR("TSK_CALLOC FAILED"); goto TNET_POLLIN_DONE; } // Receive the waiting data if(active_socket->tlshandle){ int isEncrypted; tsk_size_t tlslen = len; if((ret = tnet_tls_socket_recv(active_socket->tlshandle, &buffer, &tlslen, &isEncrypted)) == 0){ if(isEncrypted){ TSK_FREE(buffer); goto TNET_POLLIN_DONE; } if(ret == 0){ len = ret = tlslen; } } } else { if(is_stream){ ret = tnet_sockfd_recv(active_socket->fd, buffer, len, 0); } else { ret = tnet_sockfd_recvfrom(active_socket->fd, buffer, len, 0, (struct sockaddr*)&remote_addr); } } if(ret < 0){ TSK_FREE(buffer); removeSocket(i, context); TNET_PRINT_LAST_ERROR("recv/recvfrom have failed."); goto TNET_POLLIN_DONE; } if((len != (tsk_size_t)ret) && len){ len = (tsk_size_t)ret; // buffer = tsk_realloc(buffer, len); } e = tnet_transport_event_create(event_data, transport->callback_data, active_socket->fd); e->data = buffer; e->size = len; e->remote_addr = remote_addr; TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(TSK_RUNNABLE(transport), e); TNET_POLLIN_DONE: context->ufds[i].revents &= ~TNET_POLLIN; } /*================== TNET_POLLOUT ==================*/ if(context->ufds[i].revents & TNET_POLLOUT){ TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLOUT", transport->description); if(!active_socket->connected){ active_socket->connected = tsk_true; TSK_RUNNABLE_ENQUEUE(transport, event_connected, transport->callback_data, active_socket->fd); } context->ufds[i].events &= ~TNET_POLLOUT; } /*================== TNET_POLLPRI ==================*/ if(context->ufds[i].revents & TNET_POLLPRI){ TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLPRI", transport->description); } context->ufds[i].revents = 0; }/* for */ done: /* unlock context */ tsk_safeobj_unlock(context); } /* while */ bail: TSK_DEBUG_INFO("Stopped [%s] server with IP {%s} on port {%d}", transport->description, transport->master->ip, transport->master->port); return 0; }