//
//	[[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;
}
Exemplo n.º 2
0
/*=== 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;
}