/* Called on head of multibus group */ void serial_free(struct connection_in *connection) { FILE_DESCRIPTOR_OR_ERROR fd ; struct port_in * pin = connection->pown ; if ( pin->state == cs_virgin ) { return ; } fd = pin->file_descriptor ; if ( FILE_DESCRIPTOR_NOT_VALID( fd ) ) { // reopen to restore attributes fd = open( pin->init_data, O_RDWR | O_NONBLOCK | O_NOCTTY ) ; } // restore tty settings if ( FILE_DESCRIPTOR_VALID( fd ) ) { LEVEL_DEBUG("COM_close: flush"); tcflush( fd, TCIOFLUSH); LEVEL_DEBUG("COM_close: restore"); if ( tcsetattr( fd, TCSANOW, &(pin->dev.serial.oldSerialTio) ) < 0) { ERROR_CONNECT("Cannot restore port attributes: %s", pin->init_data); } } Test_and_Close( &( pin->file_descriptor) ) ; }
static void * ENET_monitor_loop( void * v ) { struct connection_in * in = v ; FILE_DESCRIPTOR_OR_ERROR file_descriptor = in->master.enet_monitor.shutdown_pipe[fd_pipe_read] ; DETACH_THREAD; do { fd_set readset; struct timeval tv = { in->master.enet_monitor.enet_scan_interval, 0, }; /* Initialize readset */ FD_ZERO(&readset); if ( FILE_DESCRIPTOR_VALID( file_descriptor ) ) { FD_SET(file_descriptor, &readset); } ENET_scan_for_adapters() ; if ( select( file_descriptor+1, &readset, NULL, NULL, &tv ) != 0 ) { break ; // don't scan any more -- perhaps a close? } } while (1) ; return VOID_RETURN ; }
static void ENET_monitor_close(struct connection_in *in) { if ( FILE_DESCRIPTOR_VALID( in->master.enet_monitor.shutdown_pipe[fd_pipe_write] ) ) { ignore_result = write( in->master.enet_monitor.shutdown_pipe[fd_pipe_write],"X",1) ; //dummy payload } Test_and_Close_Pipe(in->master.enet_monitor.shutdown_pipe) ; }
/* Usually called with BUS locked, to protect ai settings */ FILE_DESCRIPTOR_OR_ERROR ClientConnect(struct connection_in *in) { struct port_in * pin = in->pown ; FILE_DESCRIPTOR_OR_ERROR file_descriptor; struct addrinfo *ai; if ( pin->dev.tcp.ai == NULL) { LEVEL_DEBUG("Client address not yet parsed"); return FILE_DESCRIPTOR_BAD; } /* Can't change ai_ok without locking the in-device. * First try the last working address info, if it fails lock * the in-device and loop through the list until it works. * Not a perfect solution, but it should work at least. */ ai = pin->dev.tcp.ai_ok; if (ai) { file_descriptor = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if ( FILE_DESCRIPTOR_VALID(file_descriptor) ) { if (connect(file_descriptor, ai->ai_addr, ai->ai_addrlen) == 0) { return file_descriptor; } close(file_descriptor); } } ai = pin->dev.tcp.ai; // loop from first address info since it failed. do { file_descriptor = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if ( FILE_DESCRIPTOR_VALID(file_descriptor) ) { if (connect(file_descriptor, ai->ai_addr, ai->ai_addrlen) == 0) { pin->dev.tcp.ai_ok = ai; return file_descriptor; } close(file_descriptor); } } while ((ai = ai->ai_next)); pin->dev.tcp.ai_ok = NULL; ERROR_CONNECT("Socket problem"); STAT_ADD1(NET_connection_errors); return FILE_DESCRIPTOR_BAD; }
/* Called on head of multibus group */ GOOD_OR_BAD COM_read( BYTE * data, size_t length, struct connection_in *connection) { struct port_in * pin ; if ( length == 0 ) { return gbGOOD ; } if ( connection == NO_CONNECTION || data == NULL ) { // bad parameters return gbBAD ; } pin = connection->pown ; // unlike write or open, a closed connection isn't automatically opened. // the reason is that reopening won't have the data waiting. We really need // to restart the transaction from the "write" portion if ( FILE_DESCRIPTOR_NOT_VALID( pin->file_descriptor ) ) { return gbBAD ; } switch ( pin->type ) { // test the type of connection case ct_unknown: case ct_none: LEVEL_DEBUG("Unknown type"); break ; case ct_telnet: return telnet_read( data, length, connection ) ; case ct_tcp: // network is ok return COM_read_get_size( data, length, connection ) == (ssize_t) length ? gbGOOD : gbBAD ; case ct_i2c: case ct_netlink: case ct_usb: LEVEL_DEBUG("Unimplemented"); break ; case ct_serial: // serial is ok // printf("Serial read fd=%d length=%d\n",pin->file_descriptor, (int) length); { ssize_t actual = COM_read_get_size( data, length, connection ) ; if ( FILE_DESCRIPTOR_VALID( pin->file_descriptor ) ) { // tcdrain only works on serial conections tcdrain( pin->file_descriptor ); return actual == (ssize_t) length ? gbGOOD : gbBAD ; } break ; } } return gbBAD ; }
void FreeOutAll(void) { struct connection_out *next = Outbound_Control.head; struct connection_out *now; Outbound_Control.head = NULL; Outbound_Control.active = 0; while (next) { now = next; next = now->next; SAFEFREE(now->zero.name) ; SAFEFREE(now->zero.type) ; SAFEFREE(now->zero.domain) ; SAFEFREE(now->name) ; SAFEFREE(now->host) ; SAFEFREE(now->service) ; if (now->ai) { freeaddrinfo(now->ai); now->ai = NULL; } if ( FILE_DESCRIPTOR_VALID(now->file_descriptor) ) { shutdown(now->file_descriptor, SHUT_RDWR ) ; close(now->file_descriptor) ; } #if OW_ZERO if (libdnssd != NULL) { if (now->sref0) { DNSServiceRefDeallocate(now->sref0); } if (now->sref1) { DNSServiceRefDeallocate(now->sref1); } } #endif owfree(now); } }
// Wait for a resolve, then return. Timeout after 2 minutes static void ResolveWait( DNSServiceRef sref ) { FILE_DESCRIPTOR_OR_ERROR file_descriptor = DNSServiceRefSockFD(sref); if ( FILE_DESCRIPTOR_VALID(file_descriptor) ) { while (1) { fd_set readfd; struct timeval tv = { 120, 0 }; FD_ZERO(&readfd); FD_SET(file_descriptor, &readfd); if (select(file_descriptor + 1, &readfd, NULL, NULL, &tv) > 0) { if (FD_ISSET(file_descriptor, &readfd)) { DNSServiceProcessResult(sref); } } else if (errno == EINTR) { continue; } else { ERROR_CONNECT("Resolve timeout error"); } break; } } }