static BOOL log_connection (conn_t * conn, int event, config_t * conf) { switch (event) { case LOG_EVT_SERVERSTART: if (locksinit == FALSE) os_mutex_init (&connection_filelock); if (config_getConnLog (conf)) { os_mutex_lock (&connection_filelock); logfile = fopen (config_getConnLog (conf), "a"); os_mutex_unlock (&connection_filelock); } else { logfile = NULL; } break; case LOG_EVT_SERVERCLOSE: if (logfile) { os_mutex_lock (&connection_filelock); fclose (logfile); logfile = NULL; os_mutex_unlock (&connection_filelock); } break; case LOG_EVT_SERVERRESTART: log_connection (conn, LOG_EVT_SERVERCLOSE, conf); log_connection (conn, LOG_EVT_SERVERSTART, conf); break; case LOG_EVT_LOG: if (logfile) return connection_real_log (conn); break; } return TRUE; }
int handle_client(t_selfd *fd, t_server *serv) { char *cmd; int r; ssize_t swr; if (ISREADABLE(fd)) { if (((r = read_from_client(fd)) < 0 && errno != EINTR) || (r == 0)) { log_connection(((t_client *)fd->data)->sock, "Client disconnected from:"); return (destroy_connection(serv, fd)); } } if (ISWRITEABLE(fd) && (r = write_to_client(fd)) < 0 && errno != EINTR) return (destroy_connection(serv, fd)); while ((cmd = get_command(fd))) handle_add_cmd(serv, fd, cmd); swr = ring_buffer_left_read(fd->wbuff); if (!swr && fd->to_close) return (destroy_connection(serv, fd)); if (swr) CHECKWRITE(fd); CHECKREAD(fd); push_instruction(serv, fd); return (0); }
int handle_newconnection(t_selfd *fd, t_server *serv) { t_net *bind_sock; t_net *nsock; t_selfd *tmpfd; t_client *client; CHECKREAD(fd); if (!ISREADABLE(fd)) return (EXIT_FAILURE); bind_sock = (t_net*)fd->data; if (!(nsock = accept_connection(bind_sock))) return (EXIT_FAILURE); if ((!(client = malloc(sizeof(t_client)))) || !(tmpfd = create_fd(nsock->socket, client, &handle_client))) { free(client); close_connection(nsock); return (EXIT_FAILURE); } nsock->peer = peer(nsock); client->sock = nsock; log_connection(nsock, "New connection from:"); return (init_new_client(serv, tmpfd, client)); }
static bool get_info(netplay_t *netplay) { unsigned sram_size; uint32_t header[3]; const void *sram = NULL; global_t *global = global_get_ptr(); if (!socket_receive_all_blocking(netplay->fd, header, sizeof(header))) { RARCH_ERR("Failed to receive header from client.\n"); return false; } if (global->content_crc != ntohl(header[0])) { RARCH_ERR("Content CRC32s differ. Cannot use different games.\n"); return false; } if (implementation_magic_value() != ntohl(header[1])) { RARCH_ERR("Implementations differ, make sure you're using exact same libretro implementations and RetroArch version.\n"); return false; } if (core.retro_get_memory_size(RETRO_MEMORY_SAVE_RAM) != ntohl(header[2])) { RARCH_ERR("Content SRAM sizes do not correspond.\n"); return false; } if (!get_nickname(netplay, netplay->fd)) { RARCH_ERR("Failed to get nickname from client.\n"); return false; } /* Send SRAM data to our User 2. */ sram = core.retro_get_memory_data(RETRO_MEMORY_SAVE_RAM); sram_size = core.retro_get_memory_size(RETRO_MEMORY_SAVE_RAM); if (!socket_send_all_blocking(netplay->fd, sram, sram_size)) { RARCH_ERR("Failed to send SRAM data to client.\n"); return false; } if (!send_nickname(netplay, netplay->fd)) { RARCH_ERR("Failed to send nickname to client.\n"); return false; } #ifndef HAVE_SOCKET_LEGACY log_connection(&netplay->other_addr, 0, netplay->other_nick); #endif return true; }
/* Child process that finds out what to connect to and proxies */ void start_shoveler(int in_socket) { fd_set fds; struct timeval tv; int res = PROBE_AGAIN; int out_socket; struct connection cnx; init_cnx(&cnx); cnx.q[0].fd = in_socket; FD_ZERO(&fds); FD_SET(in_socket, &fds); memset(&tv, 0, sizeof(tv)); tv.tv_sec = probing_timeout; while (res == PROBE_AGAIN) { /* POSIX does not guarantee that tv will be updated, but the client can * only postpone the inevitable for so long */ res = select(in_socket + 1, &fds, NULL, NULL, &tv); if (res == -1) perror("select"); if (FD_ISSET(in_socket, &fds)) { /* Received data: figure out what protocol it is */ res = probe_client_protocol(&cnx); } else { /* Timed out: it's necessarily SSH */ cnx.proto = timeout_protocol(); break; } } if (cnx.proto->service && check_access_rights(in_socket, cnx.proto->service)) { exit(0); } /* Connect the target socket */ out_socket = connect_addr(&cnx, in_socket); CHECK_RES_DIE(out_socket, "connect"); cnx.q[1].fd = out_socket; log_connection(&cnx); flush_deferred(&cnx.q[1]); shovel(&cnx); close(in_socket); close(out_socket); if (verbose) fprintf(stderr, "connection closed down\n"); exit(0); }
static bool get_info(netplay_t *handle) { uint32_t header[3]; if (!recv_all(handle->fd, header, sizeof(header))) { RARCH_ERR("Failed to receive header from client.\n"); return false; } if (g_extern.cart_crc != ntohl(header[0])) { RARCH_ERR("Cart CRC32s differ. Cannot use different games.\n"); return false; } if (implementation_magic_value() != ntohl(header[1])) { RARCH_ERR("Implementations differ, make sure you're using exact same libretro implementations and RetroArch version.\n"); return false; } if (pretro_get_memory_size(RETRO_MEMORY_SAVE_RAM) != ntohl(header[2])) { RARCH_ERR("Cartridge SRAM sizes do not correspond.\n"); return false; } if (!get_nickname(handle, handle->fd)) { RARCH_ERR("Failed to get nickname from client.\n"); return false; } // Send SRAM data to our Player 2. const void *sram = pretro_get_memory_data(RETRO_MEMORY_SAVE_RAM); unsigned sram_size = pretro_get_memory_size(RETRO_MEMORY_SAVE_RAM); if (!send_all(handle->fd, sram, sram_size)) { RARCH_ERR("Failed to send SRAM data to client.\n"); return false; } if (!send_nickname(handle, handle->fd)) { RARCH_ERR("Failed to send nickname to client.\n"); return false; } #ifndef HAVE_SOCKET_LEGACY log_connection(&handle->other_addr, 0, handle->other_nick); #endif return true; }
BOOL log_log (conn_t * conn, int event, int subtype, config_t * conf) { switch (event) { case LOG_EVT_LOG: switch (subtype) { case LOG_TYPE_CONNECTIONESTABLISHED: return log_connection (conn, event, conn->conf); break; case LOG_TYPE_CONNECTIONCLOSE: return log_summary (conn, event, conn->conf); break; } break; default: log_connection (conn, event, conf); log_summary (conn, event, conf); break; } return TRUE; }
void log_connection_all() { int i; connection *cxt; if(! (config.cflags & CONFIG_CXWRITE)) return; for(i = 0; i < BUCKET_SIZE; i++) { cxt = bucket[i]; while(cxt) { log_connection(cxt, stdout, CX_HUMAN); cxt = cxt->next; } } }
void end_all_sessions() { connection *cxt; int cxkey; for (cxkey = 0; cxkey < BUCKET_SIZE; cxkey++) { cxt = bucket[cxkey]; while (cxt != NULL) { connection *tmp = cxt; if(config.cflags & CONFIG_CXWRITE) log_connection(cxt, stdout, CX_ENDED); cxt = cxt->next; del_connection(tmp, &bucket[cxkey]); if (cxt == NULL) { bucket[cxkey] = NULL; } } } }
static void netplay_pre_frame_spectate(netplay_t *handle) { unsigned i; if (handle->spectate_client) return; fd_set fds; FD_ZERO(&fds); FD_SET(handle->fd, &fds); struct timeval tmp_tv = {0}; if (select(handle->fd + 1, &fds, NULL, NULL, &tmp_tv) <= 0) return; if (!FD_ISSET(handle->fd, &fds)) return; struct sockaddr_storage their_addr; socklen_t addr_size = sizeof(their_addr); int new_fd = accept(handle->fd, (struct sockaddr*)&their_addr, &addr_size); if (new_fd < 0) { RARCH_ERR("Failed to accept incoming spectator.\n"); return; } int index = -1; for (i = 0; i < MAX_SPECTATORS; i++) { if (handle->spectate_fds[i] == -1) { index = i; break; } } // No vacant client streams :( if (index == -1) { close(new_fd); return; } if (!get_nickname(handle, new_fd)) { RARCH_ERR("Failed to get nickname from client.\n"); close(new_fd); return; } if (!send_nickname(handle, new_fd)) { RARCH_ERR("Failed to send nickname to client.\n"); close(new_fd); return; } size_t header_size; uint32_t *header = bsv_header_generate(&header_size, implementation_magic_value()); if (!header) { RARCH_ERR("Failed to generate BSV header.\n"); close(new_fd); return; } int bufsize = header_size; setsockopt(new_fd, SOL_SOCKET, SO_SNDBUF, CONST_CAST &bufsize, sizeof(int)); if (!send_all(new_fd, header, header_size)) { RARCH_ERR("Failed to send header to client.\n"); close(new_fd); free(header); return; } free(header); handle->spectate_fds[index] = new_fd; #ifndef HAVE_SOCKET_LEGACY log_connection(&their_addr, index, handle->other_nick); #endif }
static int http_server(void) { int server_fd = 0; int ctrl_fd = 0, ctrl_fd2 = 0; int ret, delay; struct pollfd *poll_table, *poll_entry; HTTPContext *c, *c_next; if(!(poll_table = av_mallocz_array(nb_max_http_connections + 1, sizeof(*poll_table)))) { http_log("Impossible to allocate a poll table handling %d connections.\n", nb_max_http_connections); return -1; } #if defined(PLUGIN_DVB) ctrl_fd = ff_ctl_open(1234); if (ctrl_fd < 0) { av_free(poll_table); return -1; } #endif if (my_http_addr.sin_port) { server_fd = socket_open_listen(&my_http_addr); if (server_fd < 0) { av_free(poll_table); return -1; } } if ( !server_fd) { http_log("HTTP disabled.\n"); av_free(poll_table); return -1; } #if defined(PLUGIN_SSDP) ssdp_fd = mcast_open(ssdp_ip, ssdp_port); if(ssdp_fd <= 0){ http_log("ssdp disabled\n"); } ssdp_notify(ssdp_fd, ssdp_ip, ssdp_port, "ssdp:alive"); #endif http_log("FFserver started.\n"); for(;;) { poll_entry = poll_table; #if defined(PLUGIN_DVB) if(ctrl_fd){ poll_entry->fd = ctrl_fd; poll_entry->events = POLLIN; poll_entry++; } if(ctrl_fd2){ poll_entry->fd = ctrl_fd2; poll_entry->events = POLLIN; if(ctl_msg_pending() > 0){ poll_entry->events |= POLLOUT; } poll_entry++; } #endif if (server_fd) { poll_entry->fd = server_fd; poll_entry->events = POLLIN; poll_entry++; } #if defined(PLUGIN_SSDP) if(ssdp_fd){ poll_entry->fd = ssdp_fd; poll_entry->events = POLLIN; poll_entry++; } #endif /* wait for events on each HTTP handle */ c = first_http_ctx; delay = 1500; while (c != NULL) { int fd; fd = c->fd; switch(c->state) { case HTTPSTATE_SEND_HEADER: c->poll_entry = poll_entry; poll_entry->fd = fd; poll_entry->events = POLLOUT; poll_entry++; break; case HTTPSTATE_SEND_DATA_HEADER: case HTTPSTATE_SEND_DATA: case HTTPSTATE_SEND_DATA_TRAILER: /*for TCP, we output as much as we can*/ c->poll_entry = poll_entry; poll_entry->fd = fd; poll_entry->events = POLLOUT; poll_entry++; break; case HTTPSTATE_WAIT_REQUEST: case HTTPSTATE_RECEIVE_DATA: case HTTPSTATE_WAIT_FEED: /* need to catch errors */ c->poll_entry = poll_entry; poll_entry->fd = fd; poll_entry->events = POLLIN;/* Maybe this will work */ poll_entry++; break; default: c->poll_entry = NULL; break; } c = c->next; } /* wait for an event on one connection. We poll at least every second to handle timeouts */ do { ret = poll(poll_table, poll_entry - poll_table, delay); if (ret < 0 && ff_neterrno() != AVERROR(EAGAIN) && ff_neterrno() != AVERROR(EINTR)) { av_free(poll_table); return -1; } } while (ret < 0); cur_time = av_gettime() / 1000; /* now handle the events */ for(c = first_http_ctx; c != NULL; c = c_next) { c_next = c->next; if (handle_connection(c) < 0) { log_connection(c); close_connection(c); } } poll_entry = poll_table; #if defined(PLUGIN_DVB) if(ctrl_fd){ if(poll_entry->revents & POLLIN){ ctrl_fd2 = ctl_msg_open(ctrl_fd); } poll_entry++; } if(ctrl_fd2 && poll_entry->fd == ctrl_fd2){ if(poll_entry->revents & POLLIN){ ctl_msg_recv(); ff_ctl_recv(ctl_msg_cb); }else if(poll_entry->revents & POLLOUT){ ctl_msg_send(); } poll_entry++; } #endif if(poll_entry->fd != server_fd){ printf("bad entry\n"); } if (server_fd) { if (poll_entry->revents & POLLIN) new_connection(server_fd, 0); poll_entry++; } #if defined(PLUGIN_SSDP) if (ssdp_fd) { if (poll_entry->revents & POLLIN) ssdp_response(ssdp_fd); poll_entry++; } #endif } }
void end_sessions() { connection *cxt; time_t check_time; check_time = time(NULL); int ended, expired = 0; uint32_t curcxt = 0; int iter; for (iter = 0; iter < BUCKET_SIZE; iter++) { cxt = bucket[iter]; while (cxt != NULL) { ended = 0; curcxt++; /* TCP */ if (cxt->proto == IP_PROTO_TCP) { /* * FIN from both sides */ if (cxt->s_tcpFlags & TF_FIN && cxt->d_tcpFlags & TF_FIN && (check_time - cxt->last_pkt_time) > 5) { ended = 1; } /* * RST from either side */ else if ((cxt->s_tcpFlags & TF_RST || cxt->d_tcpFlags & TF_RST) && (check_time - cxt->last_pkt_time) > 5) { ended = 1; } else if ((check_time - cxt->last_pkt_time) > TCP_TIMEOUT) { expired = 1; } } /* UDP */ else if (cxt->proto == IP_PROTO_UDP && (check_time - cxt->last_pkt_time) > 60) { expired = 1; } /* ICMP */ else if (cxt->proto == IP_PROTO_ICMP || cxt->proto == IP6_PROTO_ICMP) { if ((check_time - cxt->last_pkt_time) > 60) { expired = 1; } } /* All Other protocols */ else if ((check_time - cxt->last_pkt_time) > TCP_TIMEOUT) { expired = 1; } if (ended == 1 || expired == 1) { /* remove from the hash */ if (cxt->prev) cxt->prev->next = cxt->next; if (cxt->next) cxt->next->prev = cxt->prev; connection *tmp = cxt; if (config.cflags & CONFIG_CXWRITE) { if (expired == 1) log_connection(cxt, stdout, CX_EXPIRE); else if (ended == 1) log_connection(cxt, stdout, CX_ENDED); } ended = expired = 0; cxt = cxt->prev; //CLEAR_CXT(tmp); del_connection(tmp, &bucket[iter]); if (cxt == NULL) { bucket[iter] = NULL; } } else { cxt = cxt->prev; } } } }
int cx_track(packetinfo *pi) { struct in6_addr *ip_src; struct in6_addr *ip_dst; struct in6_addr ips; struct in6_addr ipd; uint16_t src_port = pi->s_port; uint16_t dst_port = pi->d_port; int af = pi->af; connection *cxt = NULL; connection *head = NULL; uint32_t hash; if(af== AF_INET6){ ip_src = &PI_IP6SRC(pi); ip_dst = &PI_IP6DST(pi); }else { // ugly hack :( // the way we do ip4/6 is DIRTY // FIX IT?!!? ips.s6_addr32[0] = pi->ip4->ip_src; ipd.s6_addr32[0] = pi->ip4->ip_dst; ip_src = &ips; ip_dst = &ipd; } // find the right connection bucket if (af == AF_INET) { hash = CXT_HASH4(IP4ADDR(ip_src),IP4ADDR(ip_dst)); } else if (af == AF_INET6) { hash = CXT_HASH6(ip_src,ip_dst); } cxt = bucket[hash]; head = cxt; // search through the bucket while (cxt != NULL) { // Two-way compare of given connection against connection table if (af == AF_INET) { if (CMP_CXT4(cxt,IP4ADDR(ip_src),src_port,IP4ADDR(ip_dst),dst_port)){ // Client sends first packet (TCP/SYN - UDP?) hence this is a client return cxt_update_client(cxt, pi); } else if (CMP_CXT4(cxt,IP4ADDR(ip_dst),dst_port,IP4ADDR(ip_src),src_port)) { // This is a server (Maybe not when we start up but in the long run) return cxt_update_server(cxt, pi); } } else if (af == AF_INET6) { if (CMP_CXT6(cxt,ip_src,src_port,ip_dst,dst_port)){ return cxt_update_client(cxt, pi); } else if (CMP_CXT6(cxt,ip_dst,dst_port,ip_src,src_port)){ return cxt_update_server(cxt, pi); } } cxt = cxt->next; } // bucket turned upside down didn't yeild anything. new connection cxt = cxt_new(pi); if(config.cflags & CONFIG_CXWRITE) log_connection(cxt, stdout, CX_NEW); /* * New connections are pushed on to the head of bucket[s_hash] */ cxt->next = head; if (head != NULL) { // are we doubly linked? head->prev = cxt; } bucket[hash] = cxt; pi->cxt = cxt; /* * Return value should be 1, telling to do client service fingerprinting */ return 1; }