/* Create a connection to a host trough a socks5 * If success s contain a socket to server * * If listen port != 0, it means bind mode, * so host and port will be ignored * * Return: * -1, connection error, unavailable socks server * 0, connection error, socks5 negociation * 1, connection establish, socket is set in struct s */ int new_socket_with_socks(s_socket *s, char *sockshost, int socksport, char *username, char *password, char *host, int port, int listen, int version, int ssl, int cmd) { int maxfd = 0, res; fd_set set_read, set_write; s_socks_conf conf; s_socks_client_config config; conf.config.cli = &config; char method[] = { 0x00, 0x02 }; conf.config.cli->n_allowed_method = 2; conf.config.cli->allowed_method = method; /* If no username or password we don't use auth */ if ( username == NULL || password == NULL ) --conf.config.cli->n_allowed_method; conf.config.cli->loop = 1; conf.config.cli->cmd = cmd; conf.config.cli->host = host; conf.config.cli->port = port; conf.config.cli->listen = listen; conf.config.cli->version = version; conf.config.cli->username = username; conf.config.cli->password = password; //memcpy(&conf.config, &config, sizeof(s_socks_serv_cli_config)); s_client c; init_client (&c, 0, M_CLIENT, &conf); c.soc.soc = new_client_socket(sockshost, socksport, &c.soc.adrC, &c.soc.adrS); if ( c.soc.soc < 0 ){ return -1; } #ifdef HAVE_LIBSSL /* Init SSL here */ if (ssl == 1){ TRACE(L_DEBUG, "client: socks5 enable ssl ..."); c.soc.ssl = ssl_neogiciate_client(c.soc.soc); if ( c.soc.ssl == NULL ){ ERROR(L_VERBOSE, "client: ssl error"); return -3; } TRACE(L_DEBUG, "client: ssl ok."); } #endif /* HAVE_LIBSSL */ /* Select loop */ while (conf.config.cli->loop == 1 && c.soc.soc != -1) { FD_ZERO (&set_read); FD_ZERO (&set_write); maxfd = 0; /* Adds the socket in read fds */ init_select_client(&c.soc, &c.socks, &c.buf, &maxfd, &set_read, &set_write); res = select (maxfd+1, &set_read, &set_write, NULL, NULL); if (res > 0) { dispatch_client(&c, &set_read, &set_write); } else if ( res == 0){ }else if (res < 0) { if (errno == EINTR) ; /* Received signal, it does nothing */ else { perror ("select"); disconnection(&c); return -1; } } } memcpy(s, &c.soc, sizeof(s_socket)); return (c.soc.soc >= 0); }
int main(int argc, char **argv) { char buf[1024]; fd_set * readselect = malloc(sizeof(fd_set)); fd_set * writeselect = malloc(sizeof(fd_set)); fd_set * errorselect = malloc(sizeof(fd_set)); unsigned int maxfd = 3; readsockets = array_init(); readsockets->name = "read"; writesockets = array_init(); writesockets->name = "write"; errorsockets = array_init(); errorsockets->name = "error"; buffer_socket * stdin_sock = malloc(sizeof(buffer_socket)); stdin_sock->type = SOCKTYPE_LOCAL; stdin_sock->fd = STDIN_FILENO; ringbuffer_init(&stdin_sock->rxbuffer); ringbuffer_init(&stdin_sock->txbuffer); readsockets = array_push(readsockets, stdin_sock); errorsockets = array_push(errorsockets, stdin_sock); char * printer_port = DEFAULT_PORT; int printer_baud = DEFAULT_BAUD; // TODO: parse command line options printer_socket *printer = new_printer_socket(printer_port, printer_baud); file_socket *file = NULL; /***********************************************************************\ * * * Now set up network sockets * * * \***********************************************************************/ new_listen_socket(DEFAULT_LISTEN_PORT, SOCKTYPE_CLIENT); new_listen_socket(DEFAULT_LISTEN_PORT + 1, SOCKTYPE_HTTP); /***********************************************************************\ * * * Main Loop * * * \***********************************************************************/ int running = 1; while (running) { FD_ZERO(readselect); FD_ZERO(writeselect); FD_ZERO(errorselect); for (int i = 0; i < readsockets->length; i++) { local_socket *ls = ((local_socket *) readsockets->data[i]); int fd = ls->fd; //printf("check read %d\n", ((local_socket *) readsockets->data[i])->fd); if ((ls->type == SOCKTYPE_PRINTER) || (printer->tokens > 0)) { FD_SET(fd, readselect); if (fd >= maxfd) maxfd = fd + 1; } } for (int i = 0; i < writesockets->length; i++) { local_socket *ls = ((local_socket *) writesockets->data[i]); int fd = ls->fd; //printf("check write %d\n", ((local_socket *) writesockets->data[i])->fd); if ((ls->type != SOCKTYPE_PRINTER) || (printer->tokens > 0)) { FD_SET(fd, writeselect); if (fd >= maxfd) maxfd = fd + 1; } } for (int i = 0; i < errorsockets->length; i++) { local_socket *ls = ((local_socket *) errorsockets->data[i]); int fd = ls->fd; //printf("check error %d\n", ((local_socket *) errorsockets->data[i])->fd); FD_SET(((local_socket *) errorsockets->data[i])->fd, errorselect); if (fd >= maxfd) maxfd = fd + 1; } select(maxfd, readselect, writeselect, errorselect, NULL); /*******************************************************************\ * * * Check Errors * * * \*******************************************************************/ for (int i = 0; i < errorsockets->length; i++) { local_socket *s = (local_socket *) errorsockets->data[i]; if (FD_ISSET(s->fd, errorselect)) { printf("error on %d: %p\n", s->fd, s); switch (s->type) { case SOCKTYPE_LOCAL: break; case SOCKTYPE_PRINTER: break; case SOCKTYPE_CLIENT: break; case SOCKTYPE_LISTEN: break; } /* switch s->type */ } /* if FD_ISSET fd, errorselect */ } /* for errorsockets */ /*******************************************************************\ * * * Check Readable Sockets * * * \*******************************************************************/ for (int i = 0; i < readsockets->length; i++) { local_socket *s = (local_socket *) readsockets->data[i]; if (FD_ISSET(s->fd, readselect)) { //printf("read %d (type %d)\n", s->fd, s->type); switch (s->type) { case SOCKTYPE_LOCAL: { buffer_socket *sock = (buffer_socket *) s; unsigned int r = ringbuffer_writefromfd(&sock->rxbuffer, s->fd, ringbuffer_canwrite(&sock->rxbuffer)); if (r == 0) { printf("EOF on stdin, exiting...\n"); exit(0); } break; } case SOCKTYPE_CLIENT: { client_socket *sock = (client_socket *) s; unsigned int r = ringbuffer_writefromfd(&sock->inbuffer, s->fd, ringbuffer_canwrite(&sock->inbuffer)); //printf("writefromfd %p %d %d got %d nl %d\n", &sock->rxbuffer, s->fd, ringbuffer_canwrite(&sock->rxbuffer), r, sock->rxbuffer.nl); if (r == 0) { sock2a(&sock->addr, buf, BUFFER_SIZE); printf("client %s disconnected\n", buf); close(sock->fd); readsockets = array_delete(readsockets, sock); writesockets = array_delete(writesockets, sock); errorsockets = array_delete(errorsockets, sock); free(sock); sock = NULL; } else if (sock->inbuffer.nl > 0) { char linebuffer[256]; while (ringbuffer_peekline(&sock->inbuffer, linebuffer, sizeof(linebuffer))) { switch (detect_line_type(linebuffer)) { case LINETYPE_GCODE: { unsigned int i = ringbuffer_readline(&sock->rxbuffer, linebuffer, sizeof(linebuffer)); ringbuffer_write(&sock->rxbuffer, linebuffer, i); break; }; case LINETYPE_SIMPLECMD: { unsigned int i = ringbuffer_readline(&sock->rxbuffer, linebuffer, sizeof(linebuffer)); parse_line(linebuffer); break; }; } } } break; } case SOCKTYPE_PRINTER: { //printf("can read printer\n"); printer_socket *sock = (printer_socket *) s; unsigned int r = ringbuffer_writefromfd(&sock->rxbuffer, s->fd, BUFFER_SIZE); if (r == 0) { //printf(" %d bytes: printer disconnected, trying to reconnect...\n", r); close(s->fd); readsockets = array_delete(readsockets, sock); writesockets = array_delete(writesockets, sock); errorsockets = array_delete(errorsockets, sock); free(sock); sock = NULL; sock = new_printer_socket(printer_port, printer_baud); readsockets = array_push(readsockets, sock); errorsockets = array_push(errorsockets, sock); } else { //printf(" %d bytes, %d newlines", r, sock->rxbuffer.nl); while (sock->rxbuffer.nl > 0) { char line[BUFFER_SIZE]; int r = ringbuffer_readline(&sock->rxbuffer, line, BUFFER_SIZE); if (sock->lastmsgsock->fd > 2) printf("< %s", line); int m = snprintf(buf, BUFFER_SIZE, "< %s", line); if (sock->lastmsgsock->type == SOCKTYPE_LOCAL) { int i = 0; do { i += write(sock->lastmsgsock->fd, &buf[i], m - i); } while (i < m); } else if (sock->lastmsgsock->type == SOCKTYPE_CLIENT) { //printf("client type\n"); client_socket *cs = (client_socket *) sock->lastmsgsock; ringbuffer_write(&cs->txbuffer, line, r); if (array_indexof(writesockets, cs) == -1) { writesockets = array_push(writesockets, cs); //printf("pushed %p/%d to writesockets\n", cs, cs->socket.fd); } } if (strncmp(line, "ok", 2) == 0) { //fprintf(stderr, "got token!"); if (sock->tokens < sock->maxtoken) sock->tokens++; for (int i = 0; i < errorsockets->length; i++) { if (((local_socket *) errorsockets->data[i])->type == SOCKTYPE_CLIENT) readsockets = array_push(readsockets, errorsockets->data[i]); } if (file != NULL) writesockets = array_push(writesockets, sock); //fprintf(stderr, " tokens: %d\n", sock->tokens); } else { //fprintf(stderr, "no token\n"); } } } break; } case SOCKTYPE_LISTEN: { listen_socket *ls = (listen_socket *) s; if (ls->protocol == SOCKTYPE_HTTP) { new_http_socket(ls); } else if (ls->protocol == SOCKTYPE_CLIENT) { new_client_socket(ls); } break; } case SOCKTYPE_FILE: { break; } case SOCKTYPE_HTTP: { http_socket *sock = (http_socket *) s; unsigned int r = ringbuffer_writefromfd(&sock->rxbuffer, s->fd, ringbuffer_canwrite(&sock->rxbuffer)); if (r == 0) { sock2a(&sock->addr, buf, BUFFER_SIZE); printf("client %s disconnected\n", buf); close(sock->fd); readsockets = array_delete(readsockets, sock); writesockets = array_delete(writesockets, sock); errorsockets = array_delete(errorsockets, sock); free(sock); sock = NULL; } else { } break; } } /* switch s->type */ } /* if FD_ISSET fd, readselect */ } /* for readsockets */ /*******************************************************************\ * * * Check Writable Sockets * * * \*******************************************************************/ for (int i = 0; i < writesockets->length; i++) { local_socket *s = (local_socket *) writesockets->data[i]; if (FD_ISSET(s->fd, writeselect)) { //printf("write %d", s->fd); switch (s->type) { case SOCKTYPE_LOCAL: case SOCKTYPE_CLIENT: case SOCKTYPE_HTTP: { //printf("write client socket\n"); buffer_socket *sock = (buffer_socket *) s; if (ringbuffer_canread(&sock->txbuffer) > 0) { //printf("readtofd %d %p: %d\n", s->fd, &sock->txbuffer, ringbuffer_readtofd(&sock->txbuffer, s->fd); //); } if (ringbuffer_canread(&sock->txbuffer) == 0) { //printf("client txbuffer empty\n"); writesockets = array_delete(writesockets, s); } break; } case SOCKTYPE_PRINTER: { printer_socket *sock = (printer_socket *) s; //printf("write: nl: %d\n", sock->txbuffer.nl); if (sock->rxbuffer.nl == 0) { int i = (sock->lastmsgindex + 1) % errorsockets->length; for (int j = 0; j <= errorsockets->length; j++) { buffer_socket * x = errorsockets->data[i]; if (x->type == SOCKTYPE_LOCAL || x->type == SOCKTYPE_CLIENT || x->type == SOCKTYPE_FILE) { int r = ringbuffer_readline(&x->rxbuffer, buf, BUFFER_SIZE); ringbuffer_write(&printer->txbuffer, buf, r); sock->lastmsgsock = (local_socket *) x; sock->lastmsgindex = i; break; } i = (i + 1) % errorsockets->length; } } if (sock->txbuffer.nl > 0) { //printf("write: nl: %d\n", sock->txbuffer.nl); unsigned int r = ringbuffer_readline(&sock->txbuffer, buf, BUFFER_SIZE); buf[r] = 0; printf(">>> %s", buf); int i = 0; do { i += write(s->fd, &buf[i], r - i); } while (i < r); sock->tokens--; if (sock->tokens == 0) { for (int i = 0; i < errorsockets->length; i++) { if (((local_socket *) errorsockets->data[i])->type == SOCKTYPE_CLIENT) readsockets = array_delete(readsockets, errorsockets->data[i]); } } } else if ((sock->tokens > 0) && (file != NULL) && (file->paused == 0)) { if ((ringbuffer_canwrite(&file->rxbuffer) > 0) && (file->eof == 0)) { int w = ringbuffer_writefromfd(&file->rxbuffer, file->fd, BUFFER_SIZE); if (w == 0) file->eof = 1; } if (file->rxbuffer.nl > 0) { int r = ringbuffer_readline(&file->rxbuffer, buf, BUFFER_SIZE); buf[r] = 0; printf(">>> %s", buf); int i = 0; do { i += write(s->fd, &buf[i], r - i); } while (i < r); sock->tokens--; } else if (file->eof) { // file is completely printed printf("File %s complete. Print time: \n", file->filename); // TODO:close file } } if ((ringbuffer_canread(&sock->txbuffer) == 0) || (sock->tokens == 0)) writesockets = array_delete(writesockets, sock); break; } } /* switch s->type */ } /* if FD_ISSET fd, writeselect */ } /* for writesockets */ } /* while running */ return 0; } /* main() */