enum evcom_stream_state evcom_stream_state (evcom_stream *stream) { if (stream->recvfd < 0 && stream->sendfd && stream->flags == 0) { return EVCOM_INITIALIZED; } if (stream->recvfd < 0 && stream->sendfd < 0) return EVCOM_CLOSED; if (!CONNECTED(stream)) return EVCOM_CONNECTING; if (GOT_CLOSE(stream)) { if (READABLE(stream)) { return EVCOM_CONNECTED_RO; } else { return EVCOM_CLOSING; } } if (READABLE(stream) && WRITABLE(stream)) return EVCOM_CONNECTED_RW; if (WRITABLE(stream)) return EVCOM_CONNECTED_WO; if (READABLE(stream)) return EVCOM_CONNECTED_RO; return EVCOM_CLOSING; }
int socket_tcpu_init(struct socket *sock) { struct tcp_data *td; struct tcpcb *tp; td = (struct tcp_data *)tcp_data_init(sock); BUFFOUTEND(sock) = BUFF_OUT(sock)->buf + MAX_BUF; tp=GET_TCPCB(sock); tp->t_state = TCPS_CLOSED; tp->sock = sock; /* init timer */ tp->t_timer[0] = 0; tp->t_timer[1] = 0; tp->t_timer[2] = TCPTV_KEEP_INIT; tp->t_timer[3] = 0; tp->t_template = NULL; CONNECTED(sock) = 0; return ((int) sock); }
void decr_mysql2_client(mysql_client_wrapper *wrapper) { wrapper->refcount--; if (wrapper->refcount == 0) { #ifndef _WIN32 if (CONNECTED(wrapper) && !wrapper->automatic_close) { /* The client is being garbage collected while connected. Prevent * mysql_close() from sending a mysql-QUIT or from calling shutdown() on * the socket by invalidating it. invalidate_fd() will drop this * process's reference to the socket only, while a QUIT or shutdown() * would render the underlying connection unusable, interrupting other * processes which share this object across a fork(). */ if (invalidate_fd(wrapper->client->net.fd) == Qfalse) { fprintf(stderr, "[WARN] mysql2 failed to invalidate FD safely\n"); close(wrapper->client->net.fd); } wrapper->client->net.fd = -1; } #endif nogvl_close(wrapper); xfree(wrapper->client); xfree(wrapper); } }
/* call-seq: * client.ping * * Checks whether the connection to the server is working. If the connection * has gone down and auto-reconnect is enabled an attempt to reconnect is made. * If the connection is down and auto-reconnect is disabled, ping returns an * error. */ static VALUE rb_mysql_client_ping(VALUE self) { GET_CLIENT(self); if (!CONNECTED(wrapper)) { return Qfalse; } else { return (VALUE)rb_thread_call_without_gvl(nogvl_ping, wrapper->client, RUBY_UBF_IO, 0); } }
// Disconnects port void commDisconnect() { // disconnects with serial port if connected HMENU hMenu; // Check if we're connected if (CONNECTED(TTYInfo)) { // Menu hMenu = GetMenu(ghWndMain); // get the menu handle EnableMenuItem(hMenu, ID_FILE_CONNECT, MF_ENABLED); // enable the connect menu EnableMenuItem(hMenu, ID_FILE_DISCONNECT, MF_GRAYED | MF_DISABLED); // disable the connect menu EnableMenuItem(hMenu, ID_EDIT_SETTINGS, MF_ENABLED); // enable the TTY menu // lower DTR EscapeCommFunction(COMDEV(TTYInfo), CLRDTR); // Purge reads/writes, and I/O buffer PurgeComm(COMDEV(TTYInfo), PURGE_FLAGS); CloseHandle(COMDEV(TTYInfo)); // release the handle TTYInfo.fThreadDone = TRUE; // we want the thread to end CONNECTED(TTYInfo) = FALSE; // we are now disconnected } }
/*-----------------------------------------------------------------------------*/ void InitTTYInfo() { // Initialize general TTY info COMDEV(TTYInfo) = NULL; CONNECTED(TTYInfo) = FALSE; PORT(TTYInfo) = '0'; // setting to 0 since we know nothing about // the current COM port configuration BAUDRATE(TTYInfo) = CBR_9600; BYTESIZE(TTYInfo) = 8; PARITY(TTYInfo) = NOPARITY; STOPBITS(TTYInfo) = ONESTOPBIT; InitFont(); ClearTTYContents(); }
// Connects to, sets up and configures (if virgin) port. void commConnect() { DCB dcb; HMENU hMenu; // Make sure we're not connected if (!CONNECTED(TTYInfo)) { // Menu hMenu = GetMenu(ghWndMain); // get the menu handle EnableMenuItem(hMenu, ID_FILE_CONNECT, MF_GRAYED | MF_DISABLED); // disable the connect menu EnableMenuItem(hMenu, ID_FILE_DISCONNECT, MF_ENABLED); // enable the disconnect menu EnableMenuItem(hMenu, ID_EDIT_SETTINGS, MF_GRAYED | MF_DISABLED); // disable the TTY menu COMDEV(TTYInfo) = CreateFile(gszPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); FillMemory(&dcb, sizeof(dcb), 0); dcb.BaudRate = BAUDRATE(TTYInfo); // set the baud rate dcb.ByteSize = BYTESIZE(TTYInfo); // set the data bits dcb.fParity = PARITY(TTYInfo); // set the parity dcb.StopBits = STOPBITS(TTYInfo); // set the stop bits SetCommState(COMDEV(TTYInfo), &dcb); // update the COM port configuration CONNECTED(TTYInfo) = TRUE; // we are now connected (hopefully) } // Start reading thread TTYInfo.hThread = CreateThread( NULL, // security attributes 0, // inital thread stack size, in bytes commReadThread, // address of thread function ghWndTerm, // argument for new thread 0, // creation flags &TTYInfo.hThread ); // address of returned thread ID TTYInfo.fConnected = TRUE; }
static VALUE disconnect_and_raise(VALUE self, VALUE error) { GET_CLIENT(self); wrapper->active_thread = Qnil; /* Invalidate the MySQL socket to prevent further communication. * The GC will come along later and call mysql_close to free it. */ if (CONNECTED(wrapper)) { if (invalidate_fd(wrapper->client->net.fd) == Qfalse) { fprintf(stderr, "[WARN] mysql2 failed to invalidate FD safely, closing unsafely\n"); close(wrapper->client->net.fd); } wrapper->client->net.fd = -1; } rb_exc_raise(error); }
static int stream__handshake (evcom_stream *stream) { assert(SECURE(stream)); int r = gnutls_handshake(stream->session); if (gnutls_error_is_fatal(r)) { stream->gnutls_errorno = r; stream->send_action = stream_send__close; stream->recv_action = stream_recv__close; return OKAY; } ev_timer_again(D_LOOP_(stream) &stream->timeout_watcher); if (r == GNUTLS_E_INTERRUPTED || r == GNUTLS_E_AGAIN) { if (0 == gnutls_record_get_direction((stream)->session)) { ev_io_start(D_LOOP_(stream) &(stream)->read_watcher); ev_io_stop(D_LOOP_(stream) &(stream)->write_watcher); } else { ev_io_stop(D_LOOP_(stream) &(stream)->read_watcher); ev_io_start(D_LOOP_(stream) &(stream)->write_watcher); } assert(stream->recv_action == stream__handshake); assert(stream->send_action == stream__handshake); return AGAIN; } assert(!CONNECTED(stream)); stream->flags |= EVCOM_CONNECTED; if (stream->on_connect) stream->on_connect(stream); /* evcom_stream_force_close might have been called. */ if (stream->recvfd >= 0 && stream->sendfd >= 0) { ev_io_start(D_LOOP_(stream) &stream->read_watcher); ev_io_start(D_LOOP_(stream) &stream->write_watcher); stream->send_action = stream_send__data; stream->recv_action = stream_recv__data; } return OKAY; }
static int stream__connection_established (evcom_stream *stream) { assert(!CONNECTED(stream)); #if EVCOM_HAVE_GNUTLS if (SECURE(stream)) { stream->send_action = stream__handshake; stream->recv_action = stream__handshake; } else #endif { stream->flags |= EVCOM_CONNECTED; if (stream->on_connect) stream->on_connect(stream); stream->send_action = stream_send__data; stream->recv_action = stream_recv__data; } ev_io_start(D_LOOP_(stream) &stream->write_watcher); ev_io_start(D_LOOP_(stream) &stream->read_watcher); return OKAY; }
static VALUE disconnect_and_mark_inactive(VALUE self) { GET_CLIENT(self); /* Check if execution terminated while result was still being read. */ if (!NIL_P(wrapper->active_thread)) { if (CONNECTED(wrapper)) { /* Invalidate the MySQL socket to prevent further communication. */ #ifndef _WIN32 if (invalidate_fd(wrapper->client->net.fd) == Qfalse) { rb_warn("mysql2 failed to invalidate FD safely, closing unsafely\n"); close(wrapper->client->net.fd); } #else close(wrapper->client->net.fd); #endif wrapper->client->net.fd = -1; } /* Skip mysql client check performed before command execution. */ wrapper->client->status = MYSQL_STATUS_READY; wrapper->active_thread = Qnil; } return Qnil; }
int connect_tcpu(struct socket *sock, struct sockaddr_in *servaddr, int addrlen) { struct tcpcb *tp; int error, res, timer; struct timeval timeout; struct sockaddr_in *laddr = (struct sockaddr_in *)(&sock->laddr); if((tp = GET_TCPCB(sock)) == NULL) return(-1); if (sock->state != SS_BOUND) { printf("tcp_connect: socket is not in bound state (%d != %d)\n", sock->state, SS_BOUND); return -1; } tcp_stack(tp,(struct sockaddr_in *)(&sock->laddr),servaddr); *(struct sockaddr_in *)(&tp->sock->raddr) = *servaddr; /* Save the client and server addresses in the template, minimizing work when sending a packet to the server */ tp->t_template->ti_dst.s_addr = servaddr->sin_addr.s_addr; tp->t_template->ti_dport = servaddr->sin_port; tp->t_template->ti_src.s_addr = laddr->sin_addr.s_addr; tp->t_template->ti_sport = laddr->sin_port; /* tcpstat.tcps_connattempt++; */ tp->t_template->ti_pr=IP_PROTO_TCP; tp->t_state = TCPS_SYN_SENT; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; tp->iss = (tcp_seq) NOW(); tcpu_sendseqinit(tp); if((error = tcpu_output(&tp)) < 0) return(-1); connect: timeout.tv_sec = 0; timeout.tv_usec = SLOW_TIMO; res=get_res(tp,&timeout); switch(res) { case EVENT_ERROR: return(-1); case EVENT_TIMER: { if((timer = slow_timo(tp->sock)) <= TCPT_NTIMERS) tcpu_timers(tp, timer); else goto connect; break; } default:{ tcpu_input(&tp,res); if(tp->t_state == TCPS_ESTABLISHED) { CONNECTED(sock) = 1; sock->state = SS_CONNECTED; printf ("\n\nconnect_tcpu: good return\n\n\n"); return(1); } } } if((tp->t_state == TCPS_SYN_RECEIVED) || (tp->t_state == TCPS_SYN_SENT )) { goto connect; } printf ("connect_tcpu: bad return\n"); PAUSE(TENTHS(1)); return(-1); }
static int stream_recv__data (evcom_stream *stream) { char buf[EVCOM_CHUNKSIZE]; size_t buf_size = EVCOM_CHUNKSIZE; ssize_t recved; while (READABLE(stream)) { assert(CONNECTED(stream)); if (PAUSED(stream)) { stream->recv_action = stream_recv__wait_for_resume; return OKAY; } #if EVCOM_HAVE_GNUTLS if (SECURE(stream)) { recved = gnutls_record_recv(stream->session, buf, buf_size); if (gnutls_error_is_fatal(recved)) { stream->gnutls_errorno = recved; stream->recv_action = stream_recv__close; return OKAY; } if (recved == GNUTLS_E_INTERRUPTED || recved == GNUTLS_E_AGAIN) { if (1 == gnutls_record_get_direction((stream)->session)) { fprintf(stderr, "(evcom) gnutls recv: unexpected switch direction!\n"); ev_io_stop(D_LOOP_(stream) &(stream)->read_watcher); ev_io_start(D_LOOP_(stream) &(stream)->write_watcher); } return AGAIN; } /* A server may also receive GNUTLS_E_REHANDSHAKE when a client has * initiated a andshake. In that case the server can only initiate a * handshake or terminate the connection. */ if (recved == GNUTLS_E_REHANDSHAKE) { assert(WRITABLE(stream)); stream->recv_action = stream__handshake; stream->send_action = stream__handshake; return OKAY; } } else #endif /* EVCOM_HAVE_GNUTLS */ { recved = read(stream->recvfd, buf, buf_size); } if (recved < 0) { if (errno == EAGAIN || errno == EINTR) { assert(stream->recv_action == stream_recv__data); return AGAIN; } if (errno != ECONNRESET) { evcom_perror("recv()", stream->errorno); } stream->errorno = errno; stream->recv_action = stream_recv__close; return OKAY; } ev_timer_again(D_LOOP_(stream) &stream->timeout_watcher); assert(recved >= 0); if (recved == 0) { stream->flags &= ~EVCOM_READABLE; ev_io_stop(D_LOOP_(stream) &stream->read_watcher); stream->recv_action = stream_recv__wait_for_close; } /* NOTE: EOF is signaled with recved == 0 on callback */ if (stream->on_read) stream->on_read(stream, buf, recved); if (recved == 0) { return OKAY; } } return AGAIN; }
/* Returns the number of bytes flushed to the buffer */ ssize_t evcom_stream_write (evcom_stream *stream, const char *str, size_t len) { if (!WRITABLE(stream) || GOT_CLOSE(stream)) { assert(0 && "Do not write to a closed stream"); return -1; } ssize_t sent = 0; if ( stream->send_action == stream_send__wait_for_buf && evcom_queue_empty(&stream->out) ) { assert(CONNECTED(stream)); #if EVCOM_HAVE_GNUTLS if (SECURE(stream)) { sent = gnutls_record_send(stream->session, str, len); if (gnutls_error_is_fatal(sent)) { stream->gnutls_errorno = sent; goto close; } } else #endif // EVCOM_HAVE_GNUTLS { /* TODO use writev() here? */ sent = nosigpipe_stream_send(stream, str, len); } if (sent < 0) { switch (errno) { case EPIPE: goto close; case EINTR: case EAGAIN: sent = 0; break; default: stream->errorno = errno; evcom_perror("send()", stream->errorno); goto close; } } } /* TODO else { memcpy to last buffer on head } */ assert(sent >= 0); if ((size_t)sent == len) return sent; /* sent the whole buffer */ len -= sent; str += sent; evcom_buf *b = evcom_buf_new(str, len); evcom_queue_insert_head(&stream->out, &b->queue); b->written = 0; assert(stream->sendfd >= 0); if (ATTACHED(stream)) { ev_io_start(D_LOOP_(stream) &stream->write_watcher); } return sent; close: stream->send_action = stream_send__close; stream->recv_action = stream_recv__close; if (ATTACHED(stream)) { ev_io_start(D_LOOP_(stream) &stream->write_watcher); } return -1; }
/* call-seq: * client.closed? * * @return [Boolean] */ static VALUE rb_mysql_client_closed(VALUE self) { GET_CLIENT(self); return CONNECTED(wrapper) ? Qfalse : Qtrue; }