static THREADRET raw_socket_loop_thread(THREAD *self) { CHAR buf[2*32767]; ETHCARD_LOOP_RECV_PROC_PARAM *pp, p; size_t len = 0, recvlen = 0; struct sockaddr_ll addr; fd_set set; struct timeval tv; pp = (ETHCARD_LOOP_RECV_PROC_PARAM *)self->param; p.ethcard = pp->ethcard; p.proc = pp->proc; BYTE *pkt_data; os_thread_init_complete(self); //pcap_loop(p.ethcard, 0, dispatcher_handler, (BYTE *)&p); while(os_thread_is_running(self) || os_thread_is_paused(self)) { tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&set); FD_SET(p.ethcard->fd, &set); select(p.ethcard->fd + 1, &set, NULL, NULL, &tv); if( FD_ISSET(p.ethcard->fd, &set) ) { len = sizeof(addr); recvlen = recvfrom(p.ethcard->fd,(char *)buf, sizeof(buf), 0, (struct sockaddr *)&addr, &len); if(recvlen > 0) { pkt_data = (BYTE *)buf; if(addr.sll_protocol == 0x8e88) p.proc(p.ethcard, pkt_data, recvlen); } else { //must be something wrong.... } } else { //dprintf("ETH Sleep...\n"); os_sleep(20); } os_thread_test_paused(self); } thread_ethcard_recv = os_thread_free(thread_ethcard_recv); return 0; }
/* ---------------------------------------------------------------------- * send a string to the host side IL component service. if resp is NULL * then there is no response to this call, so we should not wait for one. * * returns 0 on successful call made, -1 on failure to send call. * on success, the response is written to 'resp' pointer * -------------------------------------------------------------------- */ int vc_ilcs_execute_function( IL_FUNCTION_T func, void *data, int len, void *data2, int len2, void *bulk, int bulk_len, void *resp ) { VC_ILCS_WAIT_T *wait; int i, num; // the host MUST receive a response vc_assert( resp ); // need to atomically find free ->wait entry os_semaphore_obtain( &vc_ilcsg.wait_sem ); // we try a number of times then give up with an error message // rather than just deadlocking for (i=0; i<VC_ILCS_WAIT_TIMEOUT; i++) { num = 0; while( num < VC_ILCS_MAX_WAITING && vc_ilcsg.wait[num].resp ) num++; if ( num < VC_ILCS_MAX_WAITING || i == VC_ILCS_WAIT_TIMEOUT-1) break; // might be a fatal error if another thread is relying // on this call completing before it can complete // we'll pause until we can carry on and hope that's sufficient. os_semaphore_release( &vc_ilcsg.wait_sem ); os_sleep( 10 ); // 10 msec // if we're the vcilcs thread, then the waiters might need // us to handle their response, so try and clear those now if(os_thread_is_running(&vc_ilcsg.thread)) while(vc_ilcs_process_message(0)); os_logging_message( "%s: wait for sem", __FUNCTION__); os_semaphore_obtain( &vc_ilcsg.wait_sem ); } if(num == VC_ILCS_MAX_WAITING) { // failed to send message. vc_assert(0); os_semaphore_release( &vc_ilcsg.wait_sem ); return -1; } wait = &vc_ilcsg.wait[num]; wait->resp = resp; wait->xid = vc_ilcsg.next_xid++; os_semaphore_create( &wait->sem, OS_SEMAPHORE_TYPE_SUSPEND ); os_semaphore_obtain( &wait->sem ); // at this point, ->wait is exclusively ours () os_semaphore_release( &vc_ilcsg.wait_sem ); if(bulk) os_semaphore_obtain( &vc_ilcsg.send_sem); // write the command header. vc_ilcs_transmit( func, wait->xid, data, len, data2, len2 ); if(bulk) { int result; result = vchi_bulk_queue_transmit( vc_ilcsg.vchi_handle, // call to VCHI bulk, bulk_len, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL ); vc_assert(result == 0); os_semaphore_release( &vc_ilcsg.send_sem); } if ( !os_thread_is_running(&vc_ilcsg.thread) ) { os_semaphore_obtain( &wait->sem ); } else { // we're the vcilcs task, so wait for, and handle, incoming // messages while we're not completed for (;;) { // wait->sem will not be released until we process the response message vc_ilcs_process_message(1); // did the last message release wait->sem ? if ( !os_semaphore_obtained(&wait->sem) ) break; } } // safe to do the following - the assignment of NULL is effectively atomic os_semaphore_destroy( &wait->sem ); wait->resp = NULL; return 0; }
THREADRET tunet_thread(THREAD *self) { BOOL hasErr = FALSE; fd_set rset; fd_set wset; fd_set eset; struct timeval tv; time_t keepalive_watchDog=0; tv.tv_sec=2; tv.tv_usec=0; int ret,flags; int maxsock; int main_retry=0; char flag,connected=0; logs_append(g_logs, "TUNET_THREAD_STARTING", NULL, NULL, 0); while(os_thread_is_running(self) || os_thread_is_paused(self)) { // printf("main_socket=%d\n",main_socket); if (keepalive_watchDog) { if (time(NULL)-keepalive_watchDog>=36) { if(tunet_keepalive()==ERR) break; } } if (tunet_state==TUNET_STATE_RECV_REMAINING_DATA || tunet_state==TUNET_STATE_RECV_WELCOME) { keepalive_watchDog=time(NULL); } hasErr=FALSE; if(tunet_get_state() == TUNET_STATE_NONE) { break; } if(tunet_get_state() == TUNET_STATE_ERROR) { //an server-side error occurs when trying to login/logout logs_append(g_logs, "TUNET_ERROR", NULL, NULL, 0); break; } if (tunet_state ==TUNET_STATE_LOGOUT) { if (!connected) { break; } tunet_connect_logout_server(); } if (tunet_state==TUNET_STATE_LOGOUT||tunet_state==TUNET_STATE_LOGOUT_RECV_LOGOUT) { hasErr |= (tunet_logout_send_logout() == ERR); hasErr |= (tunet_logout_recv_logout() == ERR); if(hasErr) { //if an error occurs when LOGOUT, we can just omit it, and exit the thread. break; } os_thread_test_paused(self); os_sleep(20); }else { if(tunet_state == TUNET_STATE_LOGIN){ tunet_connect_main_server(); } if(tunet_connect_keepalive_server()==ERR){ break; } if (tunet_state == TUNET_STATE_KEEPALIVE||tunet_state==TUNET_STATE_RECV_REMAINING_DATA) { connected=1; } FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset); maxsock=0; flag=0; if (main_socket) { FD_SET(main_socket, &rset); FD_SET(main_socket, &wset); FD_SET(main_socket, &eset); if (main_socket>=maxsock) { maxsock=main_socket; } flag=1; } if (keepalive_socket) { FD_SET(keepalive_socket,&rset); FD_SET(keepalive_socket,&eset); if (keepalive_socket>=maxsock) { maxsock=keepalive_socket; } } ret=select(maxsock+1,&rset,&wset,&eset,&tv); if (ret<0) { logs_append(g_logs, "TUNET_NETWORK_ERROR", "UNKNOWN", NULL, 0); break; }else if (ret==0) { if (tunet_state==TUNET_STATE_LOGIN) { if (main_retry>=3) { logs_append(g_logs, "TUNET_NETWORK_ERROR", "MAIN", NULL, 0); break; } main_retry++; } os_thread_test_paused(self); continue; } if (flag) { if (FD_ISSET(main_socket,&wset)) { tunet_logon_send_tunet_user(); tunet_logon_reply_welcome(); } if (FD_ISSET(main_socket,&rset)) { if(tunet_logon_recv_welcome()==ERR){ logs_append(g_logs, "TUNET_NETWORK_ERROR", "RECV_WELCOME", NULL, 0); break; } if(tunet_logon_recv_remaining_data()==ERR){ logs_append(g_logs, "TUNET_NETWORK_ERROR", "RECV_REMAINING_DATA", NULL, 0); break; } } if (FD_ISSET(main_socket, &eset)) { logs_append(g_logs, "TUNET_NETWORK_ERROR", "MAIN", NULL, 0); break; } } if (FD_ISSET(keepalive_socket,&rset)) { if(tunet_keepalive()==ERR){ logs_append(g_logs, "TUNET_NETWORK_ERROR", "KEEPALIVE", NULL, 0); break; } keepalive_watchDog=time(NULL); } if (FD_ISSET(keepalive_socket, &eset)) { logs_append(g_logs, "TUNET_NETWORK_ERROR", "KEEPALIVE", NULL, 0); break; } os_thread_test_paused(self); } } main_socket = os_socket_tcp_close(main_socket); keepalive_socket = os_socket_tcp_close(keepalive_socket); logout_socket = os_socket_tcp_close(logout_socket); main_socket_buffer = buffer_clear(main_socket_buffer); keepalive_socket_buffer = buffer_clear(keepalive_socket_buffer); logout_socket_buffer = buffer_clear(logout_socket_buffer); tunet_state = TUNET_STATE_NONE; logs_append(g_logs, "TUNET_THREAD_EXITING", NULL, NULL, 0); thread_tunet = os_thread_free(thread_tunet); return 0; }
THREADRET tunet_thread(THREAD *self) { BOOL hasErr = FALSE; logs_append(g_logs, "TUNET_THREAD_STARTING", NULL, NULL, 0); while(os_thread_is_running(self) || os_thread_is_paused(self)) { if(tunet_state == TUNET_STATE_LOGIN) tunet_connect_main_server(); hasErr = FALSE; hasErr |= (tunet_logon_send_tunet_user() == ERR); hasErr |= (tunet_logon_recv_welcome() == ERR); hasErr |= (tunet_logon_reply_welcome() == ERR); hasErr |= (tunet_logon_recv_remaining_data() == ERR); hasErr |= (tunet_connect_keepalive_server() == ERR); hasErr |= (tunet_keepalive() == ERR); if(hasErr) { /* COMMENT: We won't help the user to retry for some network error shoud be dealt by the users. //a network error occurs when try to LOGIN main_socket = os_socket_tcp_close(main_socket); keepalive_socket = os_socket_tcp_close(keepalive_socket); tunet_state = TUNET_STATE_LOGIN; continue; */ break; } hasErr = FALSE; if(tunet_state == TUNET_STATE_LOGOUT) tunet_connect_logout_server(); hasErr |= (tunet_logout_send_logout() == ERR); hasErr |= (tunet_logout_recv_logout() == ERR); if(hasErr) { //if an error occurs when LOGOUT, we can just omit it, and exit the thread. break; } if(tunet_get_state() == TUNET_STATE_NONE) { //nothing to do , exit the thread break; } if(tunet_get_state() == TUNET_STATE_ERROR) { //an server-side error occurs when trying to login/logout logs_append(g_logs, "TUNET_ERROR", NULL, NULL, 0); break; } os_thread_test_paused(self); os_sleep(20); } main_socket = os_socket_tcp_close(main_socket); keepalive_socket = os_socket_tcp_close(keepalive_socket); logout_socket = os_socket_tcp_close(logout_socket); main_socket_buffer = buffer_clear(main_socket_buffer); keepalive_socket_buffer = buffer_clear(keepalive_socket_buffer); logout_socket_buffer = buffer_clear(logout_socket_buffer); tunet_state = TUNET_STATE_NONE; logs_append(g_logs, "TUNET_THREAD_EXITING", NULL, NULL, 0); thread_tunet = os_thread_free(thread_tunet); return 0; }