static int add_client_resource(struct client *client, struct client_resource *resource, gfp_t gfp_mask) { unsigned long flags; int ret; retry: if (idr_pre_get(&client->resource_idr, gfp_mask) == 0) return -ENOMEM; spin_lock_irqsave(&client->lock, flags); if (client->in_shutdown) ret = -ECANCELED; else ret = idr_get_new(&client->resource_idr, resource, &resource->handle); if (ret >= 0) { client_get(client); if (resource->release == release_iso_resource) schedule_iso_resource(container_of(resource, struct iso_resource, resource)); } spin_unlock_irqrestore(&client->lock, flags); if (ret == -EAGAIN) goto retry; return ret < 0 ? ret : 0; }
int main(int argc, char *argv[]) { int confd; struct sockaddr_in server_addr; if(argc < 5) { printf("input format is :\nput [-h hostname] [-p portname] local_filename remote_filename\nget [-h hostname] [-p portname] remote_filename local_filename\n"); exit(1); } if(!strcmp(argv[1],"put"))//输出提示。 printf("%s hostname:%s,portname:%s,local_filename:%s,remote_filename:%s\n",argv[1],argv[2],argv[3],argv[4],argv[5]); else printf("%s hostname:%s,portname:%s,local_filename:%s,remote_filename:%s\n",argv[1],argv[2],argv[3],argv[5],argv[4]); server_addr.sin_family = PF_INET;//PF_INET(协议族) server_addr.sin_addr.s_addr = inet_addr(argv[2]);//主机字节顺序转换成网络字节顺序 server_addr.sin_port = htons(atoi(argv[3]));//该函数把一个用数字和点表示的IP地址的字符串转换成一个无符号长整型 bzero(&server_addr.sin_zero,8); //sin_zero是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节 if ((confd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { perror("socket fail\n"); exit(1); } if (connect(confd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { perror("connect fail"); exit(1); } if (!strcmp(argv[1], "put")) { client_put(confd,argv[4],argv[5]); } else if (!strcmp(argv[1], "get")) { client_get(confd,argv[5],argv[4]); } else { printf("input format error\n"); } close(confd);//关闭连接 return 0; }
static int init_request(struct client *client, struct fw_cdev_send_request *request, int destination_id, int speed) { struct outbound_transaction_event *e; int ret; if (request->tcode != TCODE_STREAM_DATA && (request->length > 4096 || request->length > 512 << speed)) return -EIO; e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL); if (e == NULL) return -ENOMEM; e->client = client; e->response.length = request->length; e->response.closure = request->closure; if (request->data && copy_from_user(e->response.data, u64_to_uptr(request->data), request->length)) { ret = -EFAULT; goto failed; } e->r.resource.release = release_transaction; ret = add_client_resource(client, &e->r.resource, GFP_KERNEL); if (ret < 0) goto failed; /* Get a reference for the transaction callback */ client_get(client); fw_send_request(client->device->card, &e->r.transaction, request->tcode, destination_id, request->generation, speed, request->offset, e->response.data, request->length, complete_transaction, e); return 0; failed: kfree(e); return ret; }
/** * @brief Displays shell and parses input from user. * * Only allows integer input. * Call a function based on user selection (1-6). * If connected to a server, it disconnects before exiting. * @param r A pointer to a record structure. * @return Returns 0 on success, -1 otherwise. */ int command_parser() { printf("\n\n------------------------------------------\n" "\t1) Connect\n" "\t2) Authenticate\n" "\t3) Get\n" "\t4) Set\n" "\t5) Query\n" "\t6) Disconnect\n" "\t7) Exit\n" "------------------------------------------\n\n\n"); int option, status; struct storage_record r; bool read_success = false; while(read_success == false) { printf("Please enter your selection: "); char *l = fgets(input_buffer, sizeof input_buffer, stdin); if(l != input_buffer || (sscanf(input_buffer, "%d %s", &option, trash) != 1) || option > 7 || option < 1) printf("Invalid selection. Please enter a valid option number (1-6).\n"); else read_success = true; } switch (option) { case 1: // Connect to server status = client_connect(); break; case 2: // Authenticate the client. status = client_auth(); break; case 3: // Issue storage_get client_get(&r); n_gets++; break; case 4: // Issue storage_set client_set(&r); n_sets++; break; case 5: //Issue client_query client_query(); break; case 6: // Disconnect from server status = client_disconnect(); break; case 7: //Exit if (connected) status = client_disconnect(); status = -1; // To stop main loop printf("Goodbye!\n"); break; default: status = -1; printf("Invalid selection.\n"); break; } return status; }
int main (int argc, char **argv) { int sock, len2, len; char opcode, filename[196], mode[12] = "octet"; // default is octet struct hostent *host; struct sockaddr_in server; char* host_addr = "127.0.0.1"; FILE *fp; if (argc < 2) { printf("invalid format of command\n"); printf("Command format: ./client -h [host_addr] -P [port] -g|-p [filename] [-n] \n"); return 0; } argv++; argc--; if (strcmp(argv[0], "-h") == 0) { if (argc==1) { printf("invalid format of command\n"); printf("Command format: ./client -h [host_addr] -P [port] -g|-p [filename] [-n] \n"); return 0; } host_addr = argv[1]; argv+=2; argc-=2; } if (strcmp(argv[0], "-P")==0){ if (argc==1) { printf("invalid format of command\n"); printf("Command format: ./client -h [host_addr] -P [port] -g|-p [filename] [-n] \n"); return 0; } port = atoi(argv[1]); argv+=2; argc-=2; } if (strcmp(argv[0], "-g")==0){ if (argc==1) { printf("invalid format of command\n"); printf("Command format: ./client -h [host_addr] -P [port] -g|-p [filename] [-n] \n"); return 0; } strncpy (filename, argv[1], sizeof (filename) - 1); opcode = RRQ; argv+=2; argc-=2; } else if (strcmp(argv[0], "-p")==0){ if (argc==1) { printf("invalid format of command\n"); printf("Command format: ./client -h [host_addr] -P [port] -g|-p [filename] [-n] \n"); return 0; } strncpy (filename, argv[1], sizeof (filename) - 1); opcode = WRQ; argv+=2; argc-=2; } else if (strcmp(argv[0], "-n")==0){ strncpy (mode, "netascii", sizeof (mode) - 1); printf ("Client: The mode is set to netascii\n"); } else{ printf("Command format: ./client -h [host_addr] -P [port] -g|-p [filename] [-n] \n"); return (0); } printf("Client: server ip address: %s and port: %d \n", host_addr, port); if (!(host = gethostbyname (host_addr))) { perror ("could not obtain host address as"); exit (2); } printf("Client: Opening file: %s in %s mode \n", filename, (opcode == WRQ ? "Read": "Write") ); if(opcode == WRQ) fp = fopen (filename, "r"); else if(opcode == RRQ) fp = fopen (filename, "w"); if (fp == NULL) { printf ("Client: file could not be opened: file not found or permission denied\n"); return 0; } fclose (fp); /*Create the socket, a -1 will show us an error */ if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("Client: socket"); return 0; } // bind to an arbitrary return address // because this is the client side, we don't care about the // address since no application will connect here // INADDR_ANY is the IP address and 0 is the socket // htonl converts a long integer (e.g. address) to a network // representation (agreed-upon byte ordering bzero(&server, sizeof (server)); server.sin_family = AF_INET; memcpy (&server.sin_addr, host->h_addr, host->h_length); // server.sin_addr.s_addr = htonl (INADDR_ANY); server.sin_port = htons (port); len2 = sizeof(server); memset(buf, 0, 512); // creates RRQ packet len = request_packet(opcode, filename, mode, buf); if (sendto (sock, buf, len, 0, (struct sockaddr *) &server, len2) != len) { perror("Client: sendto has returend an error"); exit(-1); } printf("Client: %s packet sent\n", (opcode==1 ? "RRQ":"WRQ")); switch (opcode) { case RRQ: client_get(filename, server, mode, sock); break; case WRQ: client_put(filename, server, mode, sock); break; default: printf("Invalid opcode. Packet discarded."); } close(sock); return 1; }
static void schedule_iso_resource(struct iso_resource *r) { client_get(r->client); if (!schedule_delayed_work(&r->work, 0)) client_put(r->client); }
static void iso_resource_work(struct work_struct *work) { struct iso_resource_event *e; struct iso_resource *r = container_of(work, struct iso_resource, work.work); struct client *client = r->client; int generation, channel, bandwidth, todo; bool skip, free, success; spin_lock_irq(&client->lock); generation = client->device->generation; todo = r->todo; /* Allow 1000ms grace period for other reallocations. */ if (todo == ISO_RES_ALLOC && time_is_after_jiffies(client->device->card->reset_jiffies + HZ)) { if (schedule_delayed_work(&r->work, DIV_ROUND_UP(HZ, 3))) client_get(client); skip = true; } else { /* We could be called twice within the same generation. */ skip = todo == ISO_RES_REALLOC && r->generation == generation; } free = todo == ISO_RES_DEALLOC || todo == ISO_RES_ALLOC_ONCE || todo == ISO_RES_DEALLOC_ONCE; r->generation = generation; spin_unlock_irq(&client->lock); if (skip) goto out; bandwidth = r->bandwidth; fw_iso_resource_manage(client->device->card, generation, r->channels, &channel, &bandwidth, todo == ISO_RES_ALLOC || todo == ISO_RES_REALLOC || todo == ISO_RES_ALLOC_ONCE, r->transaction_data); /* * Is this generation outdated already? As long as this resource sticks * in the idr, it will be scheduled again for a newer generation or at * shutdown. */ if (channel == -EAGAIN && (todo == ISO_RES_ALLOC || todo == ISO_RES_REALLOC)) goto out; success = channel >= 0 || bandwidth > 0; spin_lock_irq(&client->lock); /* * Transit from allocation to reallocation, except if the client * requested deallocation in the meantime. */ if (r->todo == ISO_RES_ALLOC) r->todo = ISO_RES_REALLOC; /* * Allocation or reallocation failure? Pull this resource out of the * idr and prepare for deletion, unless the client is shutting down. */ if (r->todo == ISO_RES_REALLOC && !success && !client->in_shutdown && idr_find(&client->resource_idr, r->resource.handle)) { idr_remove(&client->resource_idr, r->resource.handle); client_put(client); free = true; } spin_unlock_irq(&client->lock); if (todo == ISO_RES_ALLOC && channel >= 0) r->channels = 1ULL << channel; if (todo == ISO_RES_REALLOC && success) goto out; if (todo == ISO_RES_ALLOC || todo == ISO_RES_ALLOC_ONCE) { e = r->e_alloc; r->e_alloc = NULL; } else { e = r->e_dealloc; r->e_dealloc = NULL; } e->resource.handle = r->resource.handle; e->resource.channel = channel; e->resource.bandwidth = bandwidth; queue_event(client, &e->event, &e->resource, sizeof(e->resource), NULL, 0); if (free) { cancel_delayed_work(&r->work); kfree(r->e_alloc); kfree(r->e_dealloc); kfree(r); } out: client_put(client); }
/* * Maneja los requests que hacen los clientes. */ int connection_client_handler(events_t *ev, event_t *event) { client_t *client = client_get(event->fd); char *data = "ICY 200 OK\r\n" "icy-notice1: NOTICE 1\r\n" "icy-notice2: NOTICE 2\r\n" "icy-name: STATION NAME\r\n" "icy-genre: GENRE\r\n" "icy-url: http://localhost\r\n" "content-type: audio/mpeg\r\n" "icy-pub: 1\r\n" "icy-metaint: 0\r\n" "icy-br: 128\r\n" "\r\n"; // TODO a buffer moverlo de aca, no tiene sentido alocarlo en la stack cada ves // que llamamos al event handler char buffer[512]; if(event->event_mask & EVENT_READ) { // Evento de lectura, puede ser que se cerro el cliente // o que es el inicio de la conexion y estamos por // intercambiar headers. // Otra cosa es error, no esperada. // Esta funcion es llamada cada ves que hay un evento de lectura // es decir cuando uno de nuestros clientes nos envia algo. // Esto solo sucede al inicio de la conexion cuando el servidor y // el cliente intercambian headers con informacion sobre la proxima // conexion. // // Vamos a aceptar los clientes nuevos aca, a nivel ICECAST no nivel socket // es decir que vamos a crear las estructuras necesarias para // mantener la informacion sobre los clientes. // Tambien vamos a manejar las desconexiones. Estas las vamos a detectar // por que el socket al leer nos va a devolver 0 bytes. // Si el cliente estaba en estado WAITING lo proximo que tendria // que enviar son headers de ICECAST para establecer conexion. if(client->state == CLIENT_WAITING) { #ifdef DEBUG printf("[cliente=%d] connection_client_handler(EVENT_READ):CLIENT_WAITING\n", event->fd); #endif if(socket_read_string(event->fd, buffer, sizeof(buffer)) == -1) { perror("connection_client_handler():"); return -1; } // Por ahora la verificacion es simple if(strcasestr(buffer, "icy-metadata: 1") == NULL) { #ifdef DEBUG fprintf(stderr, "[cliente=%d] Headers invalidos, desconectando\n", event->fd); #endif event_del(ev, event->fd); socket_close(event->fd); client_destroy(client); server.clients--; return 0; } // Si esta todo bien seteamos como empezando la conexion client->state = CLIENT_STARTING; return 0; } else { // Manejar desconecciones if(socket_read_string(event->fd, buffer, sizeof(buffer)) == 0) { #ifdef DEBUG fprintf(stderr, "[cliente=%d] Desconectando cliente\n", event->fd); #endif event_del(ev, event->fd); socket_close(event->fd); client_destroy(client); server.clients--; return 0; } #ifdef DEBUG fprintf(stderr, "[cliente=%d] Invalid read\n%s\n", event->fd, buffer); #endif } } else if(event->event_mask & EVENT_WRITE) { char *buffer; int ret; switch(client->state) { case CLIENT_STARTING: #ifdef DEBUG printf("[cliente=%d] connection_client_handler(EVENT_WRITE):CLIENT_STARTING\n", event->fd); #endif if(socket_write_all(event->fd, data, strlen(data)) == -1) { perror("connection_client_handler():"); return -1; } client->state = CLIENT_ACTIVE; break; case CLIENT_ACTIVE: // Servir con contenido al cliente. #ifdef DEBUG fprintf(stderr, "[cliente=%d] connection_client_handler(EVENT_WRITE):CLIENT_ACTIVE\n", event->fd); #endif ret = stream_read(server.stream, client->offset, server.buffer_size, &buffer); if(ret == -1) { perror("connection_client_handler():"); return -1; } #ifdef BANDWIDTH_THROTTLING #include <sys/time.h> struct timeval now; if(gettimeofday(&now, NULL) == -1) { perror("connection_client_handler():"); return -1; } static inline int difftime(struct timeval *t1, struct timeval *t2, useconds_t interval) { // Si hay diferencia de segundos devolver que si paso el // intervalo ya que este es medido en usecs. if(t2->tv_sec - t1->tv_sec) return 1; // si la diff entre usecs es mayor o igual que interval // podemos enviar return ((t2->tv_usec - t1->tv_usec) >= interval) ? 1 : 0; } if(!difftime(&client->last_write_ts, &now, interval)) { // El intervalo no paso, hacemos que se sirva otro socket return 0; } #endif // Podriamos haber usado socket_write_all pero no me convence, por que // si fallo, es por algo y de ultima eso lo manejamos con el offset del cliente // y los datos se los reenviamos. ret = socket_write(event->fd, buffer, server.buffer_size); if(ret == -1) { perror("connection_client_handler():"); return -1; } #ifdef BANDWIDTH_THROTTLING if(gettimeofday(&client->last_write_ts, NULL) == -1) { perror("connection_client_handler():"); return -1; } #endif client->offset += ret; // Por ahora reiniciamos el streaming. if(client->offset == server.stream->size) { #ifdef DEBUG fprintf(stderr, "[cliente=%d] connection_client_handler(CLIENT_ACTIVE):EVENT_WRITE: Se llego al final del stream, reiniciando.\n" , event->fd); #endif client->offset = 0; } break; default: break; } }