void handle_user_command(int socket, char *action) { switch(action[0]) { case 'u': puts("user moved up"); send_to_client(socket, "user moved up \r\n"); break; case 'd': puts("user moved down"); send_to_client(socket, "user moved down \r\n"); break; case 'l': puts("user moved left"); send_to_client(socket, "user moved left \r\n"); break; case 'r': puts("user moved right"); send_to_client(socket, "user moved right \r\n"); break; default: puts("undefined action"); send_to_client(socket, "no action taken \r\n"); break; } }
/** This function has been added to improve speed by buffering small amounts of data to be sent. @param t_session *session Current Session. @param const char *buffer Buffer to send. @param int size Size of buffer. @return int -1 on failure, 0 on success. */ int send_buffer(t_session *session, const char *buffer, int size) { if (size > MAX_TO_BUFFER) { if (session->output_size > 0) { if (send_to_client(session, session->output_buffer, session->output_size) == -1) { return -1; } session->output_size = 0; } if (send_to_client(session, buffer, size) == -1) { return -1; } } else if (buffer == NULL) { if (session->output_size > 0) { if (send_to_client(session, session->output_buffer, session->output_size) == -1) { return -1; } session->output_size = 0; } } else { if ((session->output_size + size > OUTPUT_BUFFER_SIZE) && (session->output_size > 0)) { if (send_to_client(session, session->output_buffer, session->output_size) == -1) { return -1; } session->output_size = 0; } memcpy(session->output_buffer + session->output_size, buffer, size); session->output_size += size; } session->bytes_sent += size; return 0; }
static void on_spistream_msg_received(uint8_t msg_id, uint8_t * data, uint16_t num_bytes) { uint8_t uart; uint8_t buf[SPISTREAM_MAX_MESSAGE_LENGTH+3]; print_message("<< Daemon", msg_id, data, num_bytes); uart = data[0]; // Check for valid uart ID if(uart >= 0 && uart <= 3) { if(msg_id > 0) { buf[0] = (uint8_t)(num_bytes & 0x00ff); buf[1] = (uint8_t)((num_bytes << 8) & 0x00ff); buf[2] = msg_id; if(num_bytes > SPISTREAM_MAX_MESSAGE_LENGTH) { fprintf(LOG_OUT, "Warning: Message has length %d, but limit " "is %d - truncating message\n", num_bytes, SPISTREAM_MAX_MESSAGE_LENGTH); num_bytes = SPISTREAM_MAX_MESSAGE_LENGTH; } memcpy(buf+3, data, num_bytes); send_to_client(buf, num_bytes+3, uart); } } }
void switcher::recv_nat_pkt(uint32_t uid, EthernetII& eth){ auto client = client_mgr_->find_session(uid); if(unlikely(!client)){ return; } client->send_to_client(eth); }
// ask power strip to toggle socket void send_cmd_toggle_socket(int32_t socket_num, int32_t socket_state) { send_buf[0] = MASTER_COMMAND_TOGGLE_SOCKET; send_buf[1] = socket_num - '1'; send_buf[2] = socket_state; send_to_client(send_buf, 3); }
//create data connection between server and user void handle_request(int port_for_data, char *fileBuff){ int data_sockfd; int integer = 1; struct sockaddr_in data_sockaddr; data_sockfd = socket(AF_INET, SOCK_STREAM, 0); if(data_sockfd < 0){ fprintf(stderr, "Error data socket()\n"); exit(1); } data_sockaddr.sin_family = AF_INET; data_sockaddr.sin_port = htons(port_for_data); data_sockaddr.sin_addr.s_addr = theHost; // set socket setsockopt(data_sockfd, SOL_SOCKET, SO_REUSEADDR, &integer, sizeof(int)); if(connect(data_sockfd, (struct sockaddr*)&data_sockaddr, sizeof(data_sockaddr)) == -1){ fprintf(stderr, "Error connecting to data socket\n"); exit(1); } send_to_client(data_sockfd, fileBuff); close(data_sockfd); }
int Chat_Player::send_err_to_client(int error_id, int source) { Block_Buffer buf; buf.make_message(80000001); buf.write_int32(error_id); buf.write_int32(source); buf.write_string(""); buf.finish_message(); return send_to_client(buf); }
void Bridge::handle_to_client() { Packet<uint8,XPoint> packet; { Mutex::Lock lock(mutex); packet=to_client.get(); } XPoint point=*packet.getExt(); send_to_client(point,packet.popExt()); }
/** Send a datachunk to the client, used by run_script() in target.c */ static int send_chunk_to_client(t_session *session, const char *chunk, int size) { char hex[10]; if (session->keep_alive) { hex[9] = '\0'; if (snprintf(hex, 9, "%x\r\n", size) < 0) { return -1; } else if (send_to_client(session, hex, strlen(hex)) == -1) { return -1; } } if (send_to_client(session, chunk, size) == -1) { return -1; } if (session->keep_alive) { if (send_to_client(session, "\r\n", 2) == -1) { return -1; } } return 0; }
/** * Send a message to one of our clients. * * @param client target for the message * @param msg message to transmit * @param can_drop could this message be dropped if the * client's queue is getting too large? */ void GSC_CLIENTS_send_to_client (struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg, int can_drop) { struct GSC_Client *c; c = find_client (client); if (NULL == c) { GNUNET_break (0); return; } send_to_client (c, msg, can_drop); }
/* send telnet option to remote */ static void send_option_to_client(struct telnet_session* telnet, rt_uint8_t option, rt_uint8_t value) { rt_uint8_t optbuf[4]; optbuf[0] = TELNET_IAC; optbuf[1] = option; optbuf[2] = value; optbuf[3] = 0; rt_mutex_take(telnet->tx_ringbuffer_lock, RT_WAITING_FOREVER); rt_ringbuffer_put(&telnet->tx_ringbuffer, optbuf, 3); rt_mutex_release(telnet->tx_ringbuffer_lock); send_to_client(telnet); }
// ask power strip how much energy it has used between start_utc and // end_utc, then print it out in kWh, as well as the cost in $. void send_cmd_energy_query(time_t start_utc, time_t end_utc) { // fill send_buf with command and two dates send_buf[0] = MASTER_COMMAND_ENERGY_QUERY; int32_to_char(start_utc, send_buf + 1); int32_to_char(end_utc, send_buf + 5); send_to_client(send_buf, 9); // now the result is in recv_buf uint32_t result[4]; double total_kwh = 0; for(int32_t i = 0; i < 3; i++) { // get the result out of recv_buf and print it out result[i] = char_to_int32(recv_buf + i * 4); double kwh = (double)result[i] / KWH_IN_J; total_kwh += kwh; printf("Socket %d: %.4fkWh, $%.4f\n", i+1, kwh, kwh * CENT_PER_KWH / 100); } printf(" Total: %.4fkWh, $%.4f\n", total_kwh, total_kwh * CENT_PER_KWH / 100); }
// ask power strip the state of each socket void send_cmd_request_socket_status() { // fill send_buf send_buf[0] = MASTER_COMMAND_REQUEST_SOCKET_STATUS; send_to_client(send_buf, 1); // now recv_buf has the result int32_t socket_current[4]; // copy the result to socket_current for(int32_t i = 0; i < 4; i++) socket_current[i] = char_to_int16(&recv_buf[1+2*i]); // then print everything out for(int32_t i = 0; i < 3; i++) { printf("Socket %d: ", i + 1); if(recv_buf[0] & (1 << i)) printf("ON"); else printf("OFF"); double current = (double)socket_current[i] / 1000; printf(", %.3fA, %.3fW\n", current, current * MAINS_VOLTAGE_RMS); } }
/** * Send a message to all of our current clients that have the right * options set. * * @param partner origin (or destination) of the message (used to check that this peer is * known to be connected to the respective client) * @param msg message to multicast * @param can_drop can this message be discarded if the queue is too long * @param options mask to use * @param type type of the embedded message, 0 for none */ static void send_to_all_clients (const struct GNUNET_PeerIdentity *partner, const struct GNUNET_MessageHeader *msg, int can_drop, uint32_t options, uint16_t type) { struct GSC_Client *c; int tm; for (c = client_head; NULL != c; c = c->next) { tm = type_match (type, c); if (! ( (0 != (c->options & options)) || ( (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) && (GNUNET_YES == tm) ) ) ) continue; /* neither options nor type match permit the message */ if ( (0 != (options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND)) && ( (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) || (GNUNET_YES == tm) ) ) continue; if ( (0 != (options & GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND)) && (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND)) ) continue; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending %u message with %u bytes to client interested in messages of type %u.\n", options, ntohs (msg->size), (unsigned int) type); GNUNET_assert ( (0 == (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) || (GNUNET_YES != tm) || (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (c->connectmap, partner)) ); send_to_client (c, msg, can_drop); } }
static rt_size_t telnet_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) { const rt_uint8_t *ptr; ptr = (rt_uint8_t*) buffer; rt_mutex_take(telnet->tx_ringbuffer_lock, RT_WAITING_FOREVER); while (size) { if (*ptr == '\n') rt_ringbuffer_putchar(&telnet->tx_ringbuffer, '\r'); if (rt_ringbuffer_putchar(&telnet->tx_ringbuffer, *ptr) == 0) /* overflow */ break; ptr++; size--; } rt_mutex_release(telnet->tx_ringbuffer_lock); /* send data to telnet client */ send_to_client(telnet); return (rt_uint32_t) ptr - (rt_uint32_t) buffer; }
/* * Function : handle_spectral_data * Description : receive data from spectral driver * Input params : pointer to ath_ssdinfo * Return : SUCCESS or FAILURE * */ int handle_spectral_data(ath_ssd_info_t *pinfo) { ath_ssd_nlsock_t *pnl = GET_ADDR_OF_NLSOCKINFO(pinfo); ath_ssd_stats_t *pstats = GET_ADDR_OF_STATS(pinfo); struct nlmsghdr *nlh = NULL; struct msghdr msg; struct iovec iov; int status = SUCCESS; int err = SUCCESS; int sockerr = 0; static int msg_pace_rate = 0; SPECTRAL_SAMP_MSG *ss_msg = NULL; SPECTRAL_SAMP_DATA *ss_data = NULL; if (!(nlh = (struct nlmsghdr*)malloc(NLMSG_SPACE(sizeof(SPECTRAL_SAMP_MSG))))) { perror("no memory"); status = FAILURE; return status; } memset(nlh, 0, NLMSG_SPACE(sizeof(SPECTRAL_SAMP_MSG))); nlh->nlmsg_len = NLMSG_SPACE(sizeof(SPECTRAL_SAMP_MSG)); nlh->nlmsg_pid = getpid(); nlh->nlmsg_flags = 0; iov.iov_base = (void *)nlh; iov.iov_len = nlh->nlmsg_len; memset(&pnl->dst_addr, 0, sizeof(pnl->dst_addr)); pnl->dst_addr.nl_family = PF_NETLINK; pnl->dst_addr.nl_pid = 0; pnl->dst_addr.nl_groups = 1; memset(&msg, 0, sizeof(msg)); msg.msg_name = (void*)&pnl->dst_addr; msg.msg_namelen = sizeof(pnl->dst_addr); msg.msg_iov = &iov; msg.msg_iovlen = 1; /* receive spectral data from spectral driver */ sockerr = recvmsg(pnl->spectral_fd, &msg, MSG_WAITALL); ss_msg = (SPECTRAL_SAMP_MSG*)NLMSG_DATA(nlh); ss_data = &ss_msg->samp_data; if (sockerr >= 0) { if (nlh->nlmsg_len) { #ifdef USE_OLD_CLASSIFIER process_spectral_msg(pinfo, ss_msg); #else new_process_spectral_msg(pinfo, ss_msg); #endif /* USE_OLD_CLASSIFIER */ msg_pace_rate++; if (msg_pace_rate == MSG_PACE_THRESHOLD) { send_to_client(pinfo, ss_msg, sizeof(SPECTRAL_SAMP_MSG)); pstats->ch[pinfo->current_channel].sent_msg++; msg_pace_rate = 0; } } if (err == -1) { perror("send err"); status = FAILURE; } } else if ((sockerr < 0) && (sockerr != EINTR)) { //perror("recvmsg"); } /* free the resource */ free(nlh); return status; }
// send current time to set the RTC in power strip void send_cmd_set_time() { send_buf[0] = MASTER_COMMAND_SET_TIME; int32_to_char(time(0), send_buf+1); send_to_client(send_buf, 5); }
int main(int argc, char *argv[]) { struct server_settings settings = {30000, 0, 1}; handle_arguments(argc, argv, &settings); struct player_character hero; init_player_character(&hero); char stat_buffer[256]; randomize_player_character_stats(&hero); snprintf(stat_buffer, 255, "STR - %i\r\nDEX - %i\r\nCON - %i\r\n", hero.strength, hero.dexterity, hero.constitution); if (catch_signal(SIGINT, handle_shutdown) == -1) { error("Can't set the interrupt handler"); } else if (settings.verbose) { puts("Interrupt handler set"); } listener_d = open_listener_socket(); bind_to_port(listener_d, settings.port_number); if (listen(listener_d, 10) == -1) { error("Can't listen"); } else if (settings.verbose) { printf("Listening on port %i", settings.port_number); } struct sockaddr_storage client_addr; unsigned int address_size = sizeof(client_addr); if (settings.verbose) { puts("Waiting for connection"); } while(1) { int connect_d = accept(listener_d, (struct sockaddr *)&client_addr, &address_size); if (connect_d == -1) { error("Can't open secondary socket"); } else if (settings.verbose) { puts("New connection started"); } if (!fork()) { close(listener_d); char input_buffer[512]; char output_buffer[512]; char send_buffer[512]; char action_buffer[3]; send_version(connect_d); while (1) { get_command(connect_d, action_buffer); puts(action_buffer); if (action_buffer[0] == 's') { puts("opening chat buffer"); listen_to_client(connect_d, input_buffer); parse_command(input_buffer, output_buffer); sprintf(send_buffer, "You said: \"%s\"\r\n", output_buffer); puts(send_buffer); send_to_client(connect_d, send_buffer); } else { handle_user_command(connect_d, action_buffer); } } close(connect_d); exit(0); } close(connect_d); } return 0; }
/* telnet server thread entry */ static void telnet_thread(void* parameter) { #define RECV_BUF_LEN 64 struct sockaddr_in addr; socklen_t addr_size; rt_uint8_t recv_buf[RECV_BUF_LEN]; rt_int32_t recv_len = 0; if ((telnet->server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { rt_kprintf("telnet: create socket failed\n"); return; } addr.sin_family = AF_INET; addr.sin_port = htons(TELNET_PORT); addr.sin_addr.s_addr = INADDR_ANY; rt_memset(&(addr.sin_zero), 0, sizeof(addr.sin_zero)); if (bind(telnet->server_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) { rt_kprintf("telnet: bind socket failed\n"); return; } if (listen(telnet->server_fd, TELNET_BACKLOG) == -1) { rt_kprintf("telnet: listen socket failed\n"); return; } /* register telnet device */ telnet->device.type = RT_Device_Class_Char; telnet->device.init = telnet_init; telnet->device.open = telnet_open; telnet->device.close = telnet_close; telnet->device.read = telnet_read; telnet->device.write = telnet_write; telnet->device.control = telnet_control; /* no private */ telnet->device.user_data = RT_NULL; /* register telnet device */ rt_device_register(&telnet->device, "telnet", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STREAM); while (1) { rt_kprintf("telnet server waiting for connection\n"); /* grab new connection */ if ((telnet->client_fd = accept(telnet->server_fd, (struct sockaddr * )&addr, &addr_size)) == -1) { continue; } rt_kprintf("new telnet client(%s:%d) connection, switch console to telnet...\n", inet_ntoa(addr.sin_addr), addr.sin_port); /* process the new connection */ /* set console */ rt_console_set_device("telnet"); /* set finsh device */ finsh_set_device("telnet"); /* set init state */ telnet->state = STATE_NORMAL; telnet->echo_mode = finsh_get_echo(); /* disable echo mode */ finsh_set_echo(0); while (1) { /* try to send all data in tx ringbuffer */ send_to_client(telnet); /* do a rx procedure */ if ((recv_len = recv(telnet->client_fd, recv_buf, RECV_BUF_LEN, 0)) > 0) { process_rx(telnet, recv_buf, recv_len); } else { /* close connection */ client_close(telnet); break; } } } }
/** * Handle #GNUNET_MESSAGE_TYPE_CORE_INIT request. * * @param cls unused * @param client new client that sent #GNUNET_MESSAGE_TYPE_CORE_INIT * @param message the `struct InitMessage` (presumably) */ static void handle_client_init (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct InitMessage *im; struct InitReplyMessage irm; struct GSC_Client *c; uint16_t msize; const uint16_t *types; uint16_t *wtypes; unsigned int i; /* check that we don't have an entry already */ c = find_client (client); if (NULL != c) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msize = ntohs (message->size); if (msize < sizeof (struct InitMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_SERVER_notification_context_add (notifier, client); im = (const struct InitMessage *) message; types = (const uint16_t *) &im[1]; msize -= sizeof (struct InitMessage); c = GNUNET_malloc (sizeof (struct GSC_Client) + msize); c->client_handle = client; c->tcnt = msize / sizeof (uint16_t); c->options = ntohl (im->options); all_client_options |= c->options; c->types = (const uint16_t *) &c[1]; c->connectmap = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_NO); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_put (c->connectmap, &GSC_my_identity, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); wtypes = (uint16_t *) & c[1]; for (i = 0; i < c->tcnt; i++) wtypes[i] = ntohs (types[i]); GSC_TYPEMAP_add (wtypes, c->tcnt); GNUNET_CONTAINER_DLL_insert (client_head, client_tail, c); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connecting to core service is interested in %u message types\n", (unsigned int) c->tcnt); /* send init reply message */ irm.header.size = htons (sizeof (struct InitReplyMessage)); irm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY); irm.reserved = htonl (0); irm.my_identity = GSC_my_identity; send_to_client (c, &irm.header, GNUNET_NO); GSC_SESSIONS_notify_client_about_sessions (c); GNUNET_SERVER_receive_done (client, GNUNET_OK); }
int main(int argc, char* argv[]){ if(argc != 2){ printf("Please enter command-line argument: port number\n"); exit(1); } int user_port = atoi(argv[1]); int i; for(i = 0; i < strlen(argv[1]); ++i){ if(!isdigit(argv[1][i])){ printf("Data port number not a valid integer\n"); exit(1); } } int control_sockfd, client_control_sockfd; control_sockfd = start_control_conn(control_sockfd, user_port); if(listen(control_sockfd, 1) < 0){ fprintf(stderr, "listen error\n"); exit(1); }else{ printf("Connection established on control port %d\n", user_port); } int fileSize, port_for_data; char *fileBuff; char *pointer; char commands[COMMANDSIZE]; char buff[BUFFSIZE]; char message[BUFFSIZE]; char cwd[BUFFSIZE]; FILE *f; DIR *d; struct dirent* in_file; while(1){ struct sockaddr_in dest; memset(&dest, 0, sizeof(dest)); socklen_t size = sizeof(struct sockaddr_in); char host[1024]; char service[20]; client_control_sockfd = accept(control_sockfd, (struct sockaddr*)&dest, &size);//NULL, NULL); if(client_control_sockfd < 0){ fprintf(stderr, "Error accepting client connection\n"); }else{ getnameinfo( (struct sockaddr*)&dest, sizeof dest, host, sizeof host, service, sizeof service, 0); printf("Connection made with client: %s %s\n", inet_ntoa(dest.sin_addr), host); } memset(buff, '\0', BUFFSIZE); if(recv(client_control_sockfd, buff, BUFFSIZE, 0) == -1){ fprintf(stderr, "Error receiving control message\n"); exit(1); } // parse the message received from client into words, from http://stackoverflow.com/questions/11198604/c-split-string-into-an-array-of-strings pointer = strtok(buff, " \n\0"); strncpy(commands, pointer, COMMANDSIZE); pointer = strtok(NULL, " \n\0");//pointer saved as data port from client command port_for_data = atoi(pointer); if(strncmp(commands, "-l", 2) == 0){ printf("List directory requested on port %d\n", port_for_data); memset(message, '\0', BUFFSIZE); // from http://stackoverflow.com/questions/11736060/how-to-read-all-files-in-a-folder-using-c // http://stackoverflow.com/questions/298510/how-to-get-the-current-directory-in-a-c-program if(getcwd(cwd, sizeof(cwd)) == NULL){ fprintf(stderr, "Error opening directory\n"); }else{ d = opendir(cwd); if(d == NULL){ strcpy(message, "Directory has no files"); send_to_client(client_control_sockfd, message);// send error message on control connection printf("Error message sent to %s\n", host); }else{ while(in_file = readdir(d)){ if(!strcmp(in_file->d_name, ".")) continue; if(!strcmp(in_file->d_name, "..")) continue; strcat(message, in_file->d_name); strcat(message, "\n"); } message[strlen(message) - 1] = '\0'; closedir(d); printf("Sending directory contents to %s: %d\n", host, port_for_data); handle_request(port_for_data, message); } } }else if(strncmp(commands, "-g", 2) == 0){ pointer = strtok(NULL, " \n\0");// parse received statement from client to get file name printf("File \"%s\" requested on port %d\n", pointer, port_for_data); f = fopen(pointer, "r");// open the file and handle errors if(f == NULL){ fprintf(stderr, "Error opening file %s. Sending error message to %s: %d\n", pointer, host, port_for_data); memset(message, '\0', BUFFSIZE); strcpy(message, "Error: file not found on server!"); send_to_client(client_control_sockfd, message);// send error message on control connection }else{ //find file size and create a buffer that size+1, this will handle short and long files fseek(f, 0, SEEK_END);// seek to end to get position fileSize = ftell(f);// get filesize fseek(f, 0, SEEK_SET);// seek to beggining fileBuff = (char*)malloc(fileSize); int len = fread(fileBuff, sizeof(char), fileSize-1, f);// copy file into fileBuff fileBuff[len] = '\0'; printf("Sending \"%s\" to %s: %d\n", pointer, host, port_for_data); handle_request(port_for_data, fileBuff);// create data connnection and send data to client free(fileBuff); } } close(client_control_sockfd); } close(control_sockfd); return 0; }
/* * handle an epoll event for a fully esablished communication channel, where * client->sock, client->pipe_in an client->pipe->out all exist. * * The function determines what happened to which file descriptor and passes * data around accordingly. */ static void handle_communication(int fd, int epfd, unsigned int event_mask) { int ret, closed, write_count, errno_orig, read_ret, write_ret; struct client_data *client = fd_to_client[fd]; struct epoll_event ev; char buf[16384]; if (event_mask & EPOLLERR || /* fd error */ event_mask & EPOLLHUP || /* fd closed */ event_mask & EPOLLRDHUP) /* fd closed */ closed = TRUE; else closed = FALSE; if (fd == client->sock) { if (closed) { /* peer gone. goodbye. */ epoll_ctl(epfd, EPOLL_CTL_DEL, client->sock, NULL); close(client->sock); fd_to_client[client->sock] = NULL; client->sock = -1; if (client->pipe_in != -1 && client->pipe_out != -1) { log_msg("User %d has disconnected from a game", client->userid); client->state = CLIENT_DISCONNECTED; unlink_client_data(client); link_client_data(client, &disconnected_list_head); /* Maybe the destination vanished before sending completed... unsent_data is likely to be an incomplete JSON object; deleting it is the only sane option. */ if (client->unsent_data) free(client->unsent_data); client->unsent_data = NULL; client->unsent_data_size = 0; } else { log_msg("Shutdown completed for game at pid %d", client->pid); client->pid = 0; cleanup_game_process(client, epfd); } } else { /* it is possible to receive or send data */ if (event_mask & EPOLLIN) { do { write_ret = -2; read_ret = read(client->sock, buf, sizeof (buf)); if (read_ret == -1 && errno == EINTR) continue; else if (read_ret <= 0) break; write_count = 0; do { write_ret = write(client->pipe_out, &buf[write_count], read_ret - write_count); if (write_ret == -1 && errno == EINTR) continue; else if (write_ret == -1) break; write_count += write_ret; } while (write_count < read_ret); } while (read_ret == sizeof (buf) && write_ret != -1); if (read_ret <= 0 || write_ret == -1) { log_msg ("data transfer error for game process %d (read = %d, write = %d): %s", client->pid, read_ret, write_ret, strerror(errno)); cleanup_game_process(client, epfd); } } if ((event_mask & EPOLLOUT) && client->unsent_data) { write_count = send_to_client(client, NULL, 0); if (write_count == -1) log_msg("error while sending: %s", strerror(errno)); /* re-arm pipe_in notification: there may be more data to send in the pipe for which an event was already received but not acted upon */ ev.data.ptr = NULL; ev.events = EPOLLIN | EPOLLRDHUP | EPOLLET; ev.data.fd = client->pipe_in; epoll_ctl(epfd, EPOLL_CTL_MOD, client->pipe_in, &ev); } } } else if (fd == client->pipe_in) { if (closed) close_client_pipe(client, epfd); else { /* there is data to send */ if (client->unsent_data) return; /* socket isn't ready for sending */ /* oddity alert: this code originally used splice for sending. That would match the receive case above and no buffer would be required. Unfortunately sending that way is significantly slower. splice: 200ms - read+write: 0.2ms! Ouch! */ do { /* read from the pipe */ redo: ret = read(client->pipe_in, buf, sizeof (buf)); errno_orig = errno; if (ret == -1 && errno == EINTR) goto redo; /* not "continue", we don't want to check the loop condition */ else if (ret > 0) { /* write to the socket; be careful to write all of it... */ write_count = send_to_client(client, buf, ret); /* write_count != ret if no more data could be sent and the remainder buf was copied to client->unsent_data for later sending */ } else write_count = ret; } while (ret == write_count && ret == sizeof (buf)); if (ret == -1) log_msg("error while reading from pipe: %s", strerror(errno_orig)); if (write_count == -1) log_msg("error while sending: %s", strerror(errno)); } } else if (fd == client->pipe_out) { if (closed) close_client_pipe(client, epfd); else /* closed == FALSE doesn't happen for this fd: it's the write side, so there should NEVER be anything to read */ log_msg("Impossible: data readable on a write pipe?!?"); } }
/* * --------------------------------------------------------------------------- * unifi_receive_event * * Dispatcher for received signals. * * This function receives the 'to host' signals and forwards * them to the unifi linux clients. * * Arguments: * ospriv Pointer to driver's private data. * sigdata Pointer to the packed signal buffer. * siglen Length of the packed signal. * bulkdata Pointer to the signal's bulk data. * * Returns: * None. * * Notes: * The signals are received in the format described in the host interface * specification, i.e wire formatted. Certain clients use the same format * to interpret them and other clients use the host formatted structures. * Each client has to call read_unpack_signal() to transform the wire * formatted signal into the host formatted signal, if necessary. * The code is in the core, since the signals are defined therefore * binded to the host interface specification. * --------------------------------------------------------------------------- */ void unifi_receive_event(void *ospriv, CsrUint8 *sigdata, CsrUint32 siglen, const bulk_data_param_t *bulkdata) { unifi_priv_t *priv = (unifi_priv_t*)ospriv; int i, receiver_id; int client_id; CsrInt16 signal_id; func_enter(); unifi_trace(priv, UDBG5, "unifi_receive_event: " "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n", COAL_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*0) & 0xFFFF, COAL_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*1) & 0xFFFF, COAL_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*2) & 0xFFFF, COAL_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*3) & 0xFFFF, COAL_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*4) & 0xFFFF, COAL_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*5) & 0xFFFF, COAL_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*6) & 0xFFFF, COAL_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*7) & 0xFFFF, siglen); receiver_id = COAL_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)) & 0xFFF0; client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT; signal_id = COAL_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata); /* Signals with ReceiverId==0 are also reported to SME / WEXT */ if (receiver_id == 0) { /* * We must not pass MA-UNITDATA.INDICATIONs to the SME because * we can not filter them in the handler. The reason is that we * need to pass some AMP related data, but the filtering needs * be done in the 802.11->802.3 translation to avoid extra process * in the data path. * Also, we filter out the MA-UNITDATA.CONFIRMs which are not * directed to the SME. */ if ((signal_id != CSR_MA_UNITDATA_INDICATION_ID) && (signal_id != CSR_MA_UNITDATA_CONFIRM_ID)) { send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata); } #ifdef CSR_NATIVE_LINUX send_to_client(priv, priv->wext_client, receiver_id, sigdata, siglen, bulkdata); #endif } #ifdef CSR_SUPPORT_SME if (signal_id == CSR_MLME_EAPOL_CONFIRM_ID) { if (priv->m4_monitor_state == m4_wait_eapol_confirm) { unifi_trace(priv, UDBG1, "unifi_receive_event: Sending M4 Transmitted IND\n"); unifi_sys_m4_transmitted_ind(priv->smepriv); priv->m4_monitor_state = m4_idle; } } #endif if ((client_id < MAX_UDI_CLIENTS) && (&priv->ul_clients[client_id] != priv->logging_client)) { send_to_client(priv, &priv->ul_clients[client_id], receiver_id, sigdata, siglen, bulkdata); } /* * Free bulk data buffers here unless it is a CSR_MA_UNITDATA_INDICATION */ switch (signal_id) { case CSR_MA_UNITDATA_INDICATION_ID: #ifdef UNIFI_SNIFF_ARPHRD case CSR_MA_SNIFFDATA_INDICATION_ID: #endif break; default: for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { if (bulkdata->d[i].data_length != 0) { unifi_net_data_free(priv, (void *)&bulkdata->d[i]); } } } func_exit(); } /* unifi_receive_event() */