static void* do_server_write(void *arg) { struct connection_data *data = (struct connection_data *) arg; while (1) { struct data_chunk *chunk = data_take(data->client_buffer); if (chunk == NULL || chunk->data == NULL) break; int done = 0; while (done != chunk->size) { int writed = write(data->connfd, chunk->data + done, chunk->size - done); if (writed <= 0) break; done += writed; printf("L->S writed %d bytes\n", writed); } data_free_chunk(chunk); } if (is_shutdown_done(data, SHUTDOWN_READ)) pthread_exit(NULL); printf("Sending SHUTDOWN_READ for connection %d\n", data->connid); send_packet(data, TYPE_SHUTDOWN_READ, NULL, 0); shutdown(data->connfd, SHUT_WR); shutdown_connection(data, SHUTDOWN_READ); pthread_exit(NULL); }
static void* do_icmp_write(void *arg) { if (arg) {} while (1) { struct data_chunk *chunk = data_take(params->client_buffer); if (chunk == NULL) break; struct connection_data *data = (struct connection_data *) chunk->connection; if (chunk->data == NULL) { data_free_chunk(chunk); if (is_shutdown_done(data, SHUTDOWN_WRITE)) continue; printf("Sending SHUTDOWN_WRITE for connection %d\n", data->connid); send_packet(data, TYPE_SHUTDOWN_WRITE, NULL, 0); shutdown(data->connfd, SHUT_RD); shutdown_connection(data, SHUTDOWN_WRITE); continue; } int done = 0; while (done < chunk->size) { int tu_size = chunk->size - done; if (chunk->size - done > MAX_TRANSFER_UNIT) tu_size = MAX_TRANSFER_UNIT; printf("L->I writed %d bytes\n", tu_size); send_packet(data, TYPE_DATA, chunk->data + done, tu_size); done += MAX_TRANSFER_UNIT; } data_free_chunk(chunk); } pthread_exit(NULL); }
int main(int argc, char *argv[]) { // Validate Args. if (argc > 3) { printf("Incorrect num of args. Usage: http_client [Optaion: host_name] [Optional: port]\n"); exit(EXIT_FAILURE); } // Default arg values. char* host_name = "localhost"; char* port = "6444"; if(argc>1){ host_name = argv[1]; } if (argc > 2 ) { port = argv[2]; } // Create Socket. int conn_fd = 0; // Connect to server. if (-1 == connect_to_server(&conn_fd, host_name, port)) { close(conn_fd); return -1; } int ret = -1; if (0 == Play(conn_fd)) { // Shutdown properly the connection. ret = shutdown_connection(conn_fd); } close(conn_fd); return ret; }
static int32 connection_runner(void *_cookie) { connection_cookie *cookie = (connection_cookie *)_cookie; bool run = true; commands_info *ci; while (run) { net_area_info area[MAX_NET_AREAS]; net_command *command; status_t status = B_OK; struct stack_driver_args *args; int32 index; ssize_t bytes = read_port(cookie->localPort,&index,NULL,0); if (bytes < B_OK) break; if (index >= NUM_COMMANDS || index < 0) { printf("got bad command index: %lx\n",index); continue; } command = cookie->commands + index; if (clone_command_areas(area, command) < B_OK) { printf("could not clone command areas!\n"); continue; } ci = g_commands_info; while(ci && ci->op) { if (ci->op == command->op) break; ci++; } args = convert_to_local(&command->area[0],&area[0], command->data); printf("command %s (0x%lx) (index = %ld), buffer = %p, length = %ld, result = %ld\n", ci->name, command->op, index, args, command->length, command->result); switch (command->op) { case NET_STACK_OPEN: cookie->openFlags = args->u.integer; printf("Opening socket connection, mode = %lx!\n", cookie->openFlags); break; case NET_STACK_CLOSE: printf("Closing socket connection...\n"); run = false; break; case NET_STACK_SOCKET: printf("Creating stack socket... family = %d, type = %d, proto = %d\n", args->u.socket.family, args->u.socket.type, args->u.socket.proto); status = core->socket_init(&cookie->socket); if (status == 0) status = core->socket_create(cookie->socket, args->u.socket.family, args->u.socket.type, args->u.socket.proto); break; case NET_STACK_GETSOCKOPT: case NET_STACK_SETSOCKOPT: if (command->op == (int32) NET_STACK_GETSOCKOPT) { status = core->socket_getsockopt(cookie->socket, args->u.sockopt.level, args->u.sockopt.option, convert_to_local(&command->area[1], &area[1], args->u.sockopt.optval), (size_t *) &args->u.sockopt.optlen); } else { status = core->socket_setsockopt(cookie->socket, args->u.sockopt.level, args->u.sockopt.option, (const void *) convert_to_local(&command->area[1], &area[1], args->u.sockopt.optval), args->u.sockopt.optlen); } break; case NET_STACK_CONNECT: case NET_STACK_BIND: case NET_STACK_GETSOCKNAME: case NET_STACK_GETPEERNAME: { caddr_t addr = (caddr_t) convert_to_local(&command->area[1], &area[1], args->u.sockaddr.addr); switch (command->op) { case NET_STACK_CONNECT: status = core->socket_connect(cookie->socket, addr, args->u.sockaddr.addrlen); break; case NET_STACK_BIND: status = core->socket_bind(cookie->socket, addr, args->u.sockaddr.addrlen); break; case NET_STACK_GETSOCKNAME: status = core->socket_getsockname(cookie->socket, (struct sockaddr *) addr, &args->u.sockaddr.addrlen); break; case NET_STACK_GETPEERNAME: status = core->socket_getpeername(cookie->socket,(struct sockaddr *) addr, &args->u.sockaddr.addrlen); break; } break; } case NET_STACK_LISTEN: status = core->socket_listen(cookie->socket, args->u.integer); break; case NET_STACK_GET_COOKIE: /* this is needed by accept() call, to be able to pass back * in NET_STACK_ACCEPT opcode the cookie of the filedescriptor to * use for the new accepted socket */ *((void **) args) = cookie; break; case NET_STACK_ACCEPT: { connection_cookie *otherCookie = (connection_cookie *) args->u.accept.cookie; status = core->socket_accept(cookie->socket, &otherCookie->socket, convert_to_local(&command->area[1], &area[1], args->u.accept.addr), &args->u.accept.addrlen); } case NET_STACK_SEND: { struct iovec iov; int flags = 0; iov.iov_base = convert_to_local(&command->area[1], &area[1], args->u.transfer.data); iov.iov_len = args->u.transfer.datalen; status = core->socket_writev(cookie->socket, &iov, flags); break; } case NET_STACK_RECV: { struct iovec iov; int flags = 0; iov.iov_base = convert_to_local(&command->area[1], &area[1], args->u.transfer.data); iov.iov_len = args->u.transfer.datalen; /* flags gets ignored here... */ status = core->socket_readv(cookie->socket, &iov, &flags); break; } case NET_STACK_RECVFROM: { struct msghdr *msg = (struct msghdr *) args; int received; msg->msg_name = convert_to_local(&command->area[1],&area[1],msg->msg_name); msg->msg_iov = convert_to_local(&command->area[2],&area[2],msg->msg_iov); msg->msg_control = convert_to_local(&command->area[3],&area[3],msg->msg_control); status = core->socket_recv(cookie->socket, msg, (caddr_t)&msg->msg_namelen,&received); if (status == 0) status = received; msg->msg_name = convert_to_foreign(&command->area[1],&area[1],msg->msg_name); msg->msg_iov = convert_to_foreign(&command->area[2],&area[2],msg->msg_iov); msg->msg_control = convert_to_foreign(&command->area[3],&area[3],msg->msg_control); break; } case NET_STACK_SENDTO: { struct msghdr *msg = (struct msghdr *) args; int sent; msg->msg_name = convert_to_local(&command->area[1],&area[1],msg->msg_name); msg->msg_iov = convert_to_local(&command->area[2],&area[2],msg->msg_iov); msg->msg_control = convert_to_local(&command->area[3],&area[3],msg->msg_control); status = core->socket_send(cookie->socket,msg,msg->msg_flags,&sent); if (status == 0) status = sent; msg->msg_name = convert_to_foreign(&command->area[1],&area[1],msg->msg_name); msg->msg_iov = convert_to_foreign(&command->area[2],&area[2],msg->msg_iov); msg->msg_control = convert_to_foreign(&command->area[3],&area[3],msg->msg_control); break; } case NET_STACK_NOTIFY_SOCKET_EVENT: { struct notify_socket_event_args *nsea = (struct notify_socket_event_args *) args; cookie->socket_event_port = nsea->notify_port; cookie->notify_cookie = nsea->cookie; if (cookie->socket_event_port != -1) // start notify socket event status = core->socket_set_event_callback(cookie->socket, on_socket_event, cookie, 0); else // stop notify socket event status = core->socket_set_event_callback(cookie->socket, NULL, NULL, 0); break; } case NET_STACK_SYSCTL: { status = core->net_sysctl(convert_to_local(&command->area[1],&area[1], args->u.sysctl.name), args->u.sysctl.namelen, convert_to_local(&command->area[2],&area[2],args->u.sysctl.oldp), convert_to_local(&command->area[3],&area[3],args->u.sysctl.oldlenp), convert_to_local(&command->area[4],&area[4],args->u.sysctl.newp), args->u.sysctl.newlen); break; } /* case NET_STACK_STOP: core->stop(); break; */ case NET_STACK_CONTROL_NET_MODULE: // TODO! break; case B_SET_BLOCKING_IO: cookie->openFlags &= ~O_NONBLOCK; break; case B_SET_NONBLOCKING_IO: cookie->openFlags |= O_NONBLOCK; break; case OSIOCGIFCONF: case SIOCGIFCONF: { struct ifconf *ifc = (struct ifconf *) args; ifc->ifc_buf = convert_to_local(&command->area[1], &area[1], ifc->ifc_buf); status = core->socket_ioctl(cookie->socket, command->op, (char *) args); ifc->ifc_buf = convert_to_foreign(&command->area[1], &area[1], ifc->ifc_buf); break; } default: status = core->socket_ioctl(cookie->socket,command->op, (char *) args); break; } // mark the command as done command->result = status; command->op = 0; delete_cloned_areas(area); // notify the command pipeline that we're done with the command release_sem(cookie->commandSemaphore); } cookie->runner = -1; shutdown_connection(cookie); return 0; }
void select_loop(int listenfd) { /* Common vars */ char socket_pair_buffer[2]; int nbytes; char remote_ip[INET6_ADDRSTRLEN]; int fd, fdmax; int done = 0; #ifndef NOPE_MAX_CON_CONS FdData fdDataList[MAX_NO_FDS]; #else FdData *fdDataList; LOG_ERROR_ON_NULL(fdDataList = malloc(sizeof(FdData) * MAX_NO_FDS), "Can't malloc() on fdDataList"); #endif struct timeval tv; int poll_timeout = POLL_TIMEOUT; tv.tv_sec = 0; tv.tv_usec = POLL_TIMEOUT * 1000; /* keep track of the biggest file descriptor */ fdmax = listenfd; /* so far, it's this one */ for (fd = 0; fd < fdmax; fd++) { fdDataList[fd].state = STATE_PRE_REQUEST; } #ifdef NOPE_EPOLL int eventfd; struct epoll_event event; struct epoll_event *events; eventfd = epoll_create(1234); /*Number is ignored */ if (eventfd == -1) { perror("epoll_create"); return; } event.data.fd = listenfd; event.events = EPOLLIN | EPOLLET; if (epoll_ctl(eventfd, EPOLL_CTL_ADD, listenfd, &event)) { perror("epoll_ctl"); return; } #ifdef NOPE_THREADS /* Socket Pair */ event.data.fd = socketpair_fd[1]; event.events = EPOLLIN | EPOLLET; if (epoll_ctl(eventfd, EPOLL_CTL_ADD, socketpair_fd[1], &event)) { perror("epoll_ctl_socketpair"); return; } #endif events = calloc(MAX_EVENTS, sizeof event); /* Epoll main loop */ while (1) { #ifdef NOPE_THREADS cleaner_thread(); /*Run the thread clearer */ #endif int n, e; dbgprintf(KCYN "Waiting for events \n" KNRM); n = epoll_wait(eventfd, events, MAX_EVENTS, poll_timeout); dbgprintf(KCYN "Detected %d events \n" KNRM, n); for (e = 0; e < n; e++) { if ((events[e].events & EPOLLERR) || (events[e].events & EPOLLHUP) || (!(events[e].events & EPOLLIN))) { fprintf(stderr, "epoll error detected in line %d\n", __LINE__); close(events[e].data.fd); continue; } else if (listenfd == events[e].data.fd) { while (1) { struct sockaddr in_addr; socklen_t in_len; int newfd; char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; in_len = sizeof in_addr; newfd = accept(listenfd, &in_addr, &in_len); if (newfd == -1) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { /* We have processed all incoming connections. */ break; } else { perror("accept"); break; } } else if (newfd >= MAX_NO_FDS) { /* Process some events before accepting more */ fprintf(stderr, "Reached MAX_NO_FDS at %d\n", newfd); break; } if (getnameinfo(&in_addr, in_len, hbuf, sizeof hbuf, sbuf, sizeof sbuf, NI_NUMERICHOST | NI_NUMERICSERV) == 0) { /*dbgprintf("accept()ed connection on %d (host=%s, port=%s)\n", newfd, hbuf, sbuf); */ fdDataList[newfd].state = STATE_PRE_REQUEST; new_fd_data(&fdDataList[newfd]); } /* Make the incoming socket non-blocking and add it to the list of fds to monitor. */ if (FCNTL_NONBLOCK(newfd) < 0) { perror("fcntl"); return; } event.data.fd = newfd; event.events = EPOLLIN | EPOLLET; if (epoll_ctl(eventfd, EPOLL_CTL_ADD, newfd, &event) < 0) { perror("epoll_ctl"); return; } } continue; } #ifdef NOPE_THREADS else if (socketpair_fd[1] == events[e].data.fd) { nbytes = read(events[e].data.fd, socket_pair_buffer, 1); dbgprintf(KCYN "SocketPair Read %d : %d\n" KCYN, events[e].data.fd, nbytes); if (nbytes == -1) { if (errno != EAGAIN) { /* EAGAINs we have read all data */ perror("read"); } } } #endif else { fd = events[e].data.fd; while (1) { nbytes = read(fd, fdDataList[fd].readBuffer + fdDataList[fd].readBufferIdx, MAX_REQUEST_SIZE - fdDataList[fd].readBufferLen); dbgprintf(KCYN "Read %d : %d\n" KCYN, fd, nbytes); if (nbytes == -1) { if (errno != EAGAIN) { /* EAGAINs we have read all data */ perror("read"); done = true; } break; } else if (nbytes == 0) { done = true; break; } if ((done = state_machine(fdDataList, fd, nbytes, NULL))) { break; } } if (done) { clear_connection_baggage(fdDataList, fd, NULL); } } } } #else /* Select stuff * Thank you Brian "Beej Jorgensen" Hall */ fd_set master; // pMaster file descriptor list fd_set read_fds; // temp file descriptor list for select() FD_ZERO(&master); /* clear the pMaster and temp sets */ FD_ZERO(&read_fds); /* add the listener to the master set */ FD_SET(listenfd, &master); /* Select main loop */ while (1) { #ifdef NOPE_THREADS cleaner_thread(); /*Run the thread clearer */ #endif read_fds = master; /* copy it */ dbgprintf(KRED "Select blocking\n" KNRM); if (select(fdmax + 1, &read_fds, NULL, NULL, NULL) == -1) { perror("select"); exit(4); } dbgprintf(KRED "Select blocked\n" KNRM); /* run through the existing connections looking for data to read */ for (fd = 0; fd <= fdmax; fd++) { if (!FD_ISSET(fd, &read_fds)) // we got one!! continue; if (fd == listenfd) { accept_connection(fdDataList, listenfd, remote_ip, &fdmax, &master); break; } nbytes = recv(fd, fdDataList[fd].readBuffer + fdDataList[fd].readBufferIdx, MAX_REQUEST_SIZE - fdDataList[fd].readBufferLen, 0); /* read failure */ if (nbytes <= 0) { shutdown_connection(fdDataList, fd, nbytes, &master); break; } /* State Machine */ done = state_machine(fdDataList, fd, nbytes, &master); if (done) { clear_connection_baggage(fdDataList, fd, &master); } } // END looping through file descriptors } // END for(;;)--and you thought it would never end! #endif return; }