int ps4LinkLseek(int fd, int offset, int whence) { ps4link_pkt_lseek_req *lseekreq; ps4link_pkt_file_rly *lseekrly; if (ps4LinkGetValue(FILEIO_SOCK) < 0) { return -1; } debugNetPrintf(DEBUG,"[PS4LINK] file lseek req (fd: %d)\n", fd); lseekreq = (ps4link_pkt_lseek_req *)&send_packet[0]; lseekrly = (ps4link_pkt_file_rly *)&recv_packet[0]; lseekreq->cmd = sceNetHtonl(PS4LINK_LSEEK_CMD); lseekreq->len = sceNetHtons((unsigned short)sizeof(ps4link_pkt_lseek_req)); lseekreq->fd = sceNetHtonl(fd); lseekreq->offset = sceNetHtonl(offset); lseekreq->whence = sceNetHtonl(whence); if(ps4link_send(ps4LinkGetValue(FILEIO_SOCK), lseekreq, sizeof(ps4link_pkt_lseek_req), MSG_DONTWAIT) < 0) { return -1; } if(!ps4link_accept_pkt(ps4LinkGetValue(FILEIO_SOCK), (char *)lseekrly,sizeof(ps4link_pkt_file_rly), PS4LINK_LSEEK_RLY)) { debugNetPrintf(DEBUG,"[PS4LINK] ps4link_lseek_file: did not receive PS4LINK_LSEEK_RLY\n"); return -1; } debugNetPrintf(DEBUG,"[PS4LINK] ps4link_lseek_file: lseek reply received (ret %d)\n",sceNetNtohl(lseekrly->retval)); return sceNetNtohl(lseekrly->retval); }
int ps4LinkDclose(int fd) { ps4link_pkt_close_req *closereq; ps4link_pkt_file_rly *closerly; if (ps4LinkGetValue(FILEIO_SOCK) < 0) { return -1; } debugNetPrintf(DEBUG,"[PS4LINK] ps4link_file: dir close req (fd: %d)\n", fd); closereq = (ps4link_pkt_close_req *)&send_packet[0]; closerly = (ps4link_pkt_file_rly *)&recv_packet[0]; closereq->cmd = sceNetHtonl(PS4LINK_CLOSEDIR_CMD); closereq->len = sceNetHtons((unsigned short)sizeof(ps4link_pkt_close_req)); closereq->fd = sceNetHtonl(fd); if (ps4link_send(ps4LinkGetValue(FILEIO_SOCK), closereq, sizeof(ps4link_pkt_close_req), MSG_DONTWAIT) < 0) { return -1; } if(!ps4link_accept_pkt(ps4LinkGetValue(FILEIO_SOCK), (char *)closerly, sizeof(ps4link_pkt_file_rly), PS4LINK_CLOSEDIR_RLY)) { debugNetPrintf(DEBUG,"[PS4LINK] ps4link_close_dir: did not receive PS4LINK_CLOSEDIR_RLY\n"); return -1; } debugNetPrintf(DEBUG,"[PS4LINK] dir close reply received (ret %d)\n", sceNetNtohl(closerly->retval)); return sceNetNtohl(closerly->retval); }
int ps4LinkDopen(const char *dirname) { ps4link_pkt_open_req *openreq; ps4link_pkt_file_rly *openrly; if (ps4LinkGetValue(FILEIO_SOCK) < 0) { return -1; } debugNetPrintf(DEBUG,"[PS4LINK] dir open req (%s)\n", dirname); openreq = (ps4link_pkt_open_req *)&send_packet[0]; // Build packet openreq->cmd = sceNetHtonl(PS4LINK_OPENDIR_CMD); openreq->len = sceNetHtons((unsigned short)sizeof(ps4link_pkt_open_req)); openreq->flags = sceNetHtonl(0); strncpy(openreq->path, dirname, PS4LINK_MAX_PATH); openreq->path[PS4LINK_MAX_PATH - 1] = 0; // Make sure it's null-terminated if (ps4link_send(ps4LinkGetValue(FILEIO_SOCK), openreq, sizeof(ps4link_pkt_open_req), MSG_DONTWAIT) < 0) { return -1; } if (!ps4link_accept_pkt(ps4LinkGetValue(FILEIO_SOCK), recv_packet, sizeof(ps4link_pkt_file_rly), PS4LINK_OPENDIR_RLY)) { debugNetPrintf(DEBUG,"[PS4LINK] ps4link_open_dir: did not receive OPENDIR_RLY\n"); return -1; } openrly = (ps4link_pkt_file_rly *)recv_packet; debugNetPrintf(DEBUG,"[PS4LINK] dir open reply received (ret %d)\n", sceNetNtohl(openrly->retval)); return sceNetNtohl(openrly->retval); }
int ps4LinkRmdir(const char *dirname) { ps4link_pkt_rmdir_req *rmdirreq; ps4link_pkt_file_rly *rmdirrly; if (ps4LinkGetValue(FILEIO_SOCK) < 0) { return -1; } debugNetPrintf(DEBUG,"[PS4LINK] ps4link_file: remove dir req (%s)\n", dirname); rmdirreq = (ps4link_pkt_rmdir_req *)&send_packet[0]; // Build packet rmdirreq->cmd = sceNetHtonl(PS4LINK_RMDIR_CMD); rmdirreq->len = sceNetHtons((unsigned short)sizeof(ps4link_pkt_rmdir_req)); strncpy(rmdirreq->name, dirname, PS4LINK_MAX_PATH); rmdirreq->name[PS4LINK_MAX_PATH - 1] = 0; // Make sure it's null-terminated if (ps4link_send(ps4LinkGetValue(FILEIO_SOCK), rmdirreq, sizeof(ps4link_pkt_rmdir_req), MSG_DONTWAIT) < 0) { return -1; } if (!ps4link_accept_pkt(ps4LinkGetValue(FILEIO_SOCK), recv_packet, sizeof(ps4link_pkt_file_rly), PS4LINK_RMDIR_RLY)) { debugNetPrintf(DEBUG,"[PS4LINK] ps4link_file: ps4link_rmdir: did not receive RMDIR_RLY\n"); return -1; } rmdirrly = (ps4link_pkt_file_rly *)recv_packet; debugNetPrintf(DEBUG,"[PS4LINK] ps4link_file: remove dir reply received (ret %d)\n", sceNetNtohl(rmdirrly->retval)); return sceNetNtohl(rmdirrly->retval); }
static void cmd_PASV_func(ClientInfo *client) { int ret; UNUSED(ret); char cmd[512]; unsigned int namelen; SceNetSockaddrIn picked; /* Create data mode socket name */ char data_socket_name[64]; sprintf(data_socket_name, "FTPVita_client_%i_data_socket", client->num); /* Create the data socket */ client->data_sockfd = sceNetSocket(data_socket_name, PSP2_NET_AF_INET, PSP2_NET_SOCK_STREAM, 0); DEBUG("PASV data socket fd: %d\n", client->data_sockfd); /* Fill the data socket address */ client->data_sockaddr.sin_family = PSP2_NET_AF_INET; client->data_sockaddr.sin_addr.s_addr = sceNetHtonl(PSP2_NET_INADDR_ANY); /* Let the PSVita choose a port */ client->data_sockaddr.sin_port = sceNetHtons(0); /* Bind the data socket address to the data socket */ ret = sceNetBind(client->data_sockfd, (SceNetSockaddr *)&client->data_sockaddr, sizeof(client->data_sockaddr)); DEBUG("sceNetBind(): 0x%08X\n", ret); /* Start listening */ ret = sceNetListen(client->data_sockfd, 128); DEBUG("sceNetListen(): 0x%08X\n", ret); /* Get the port that the PSVita has chosen */ namelen = sizeof(picked); sceNetGetsockname(client->data_sockfd, (SceNetSockaddr *)&picked, &namelen); DEBUG("PASV mode port: 0x%04X\n", picked.sin_port); /* Build the command */ sprintf(cmd, "227 Entering Passive Mode (%hhu,%hhu,%hhu,%hhu,%hhu,%hhu)\n", (vita_addr.s_addr >> 0) & 0xFF, (vita_addr.s_addr >> 8) & 0xFF, (vita_addr.s_addr >> 16) & 0xFF, (vita_addr.s_addr >> 24) & 0xFF, (picked.sin_port >> 0) & 0xFF, (picked.sin_port >> 8) & 0xFF); client_send_ctrl_msg(client, cmd); /* Set the data connection type to passive! */ client->data_con_type = FTP_DATA_CONNECTION_PASSIVE; }
int ps4LinkDread(int fd, struct dirent *dir) { ps4link_pkt_dread_req *dirreq; ps4link_pkt_dread_rly *dirrly; struct dirent *dirent; if (ps4LinkGetValue(FILEIO_SOCK) < 0) { return -1; } debugNetPrintf(DEBUG,"[PS4LINK] dir read req (%x)\n", fd); dirreq = (ps4link_pkt_dread_req *)&send_packet[0]; // Build packet dirreq->cmd = sceNetHtonl(PS4LINK_READDIR_CMD); dirreq->len = sceNetHtons((unsigned short)sizeof(ps4link_pkt_dread_req)); dirreq->fd = sceNetHtonl(fd); if (ps4link_send(ps4LinkGetValue(FILEIO_SOCK), dirreq, sizeof(ps4link_pkt_dread_req), MSG_DONTWAIT) < 0) { return -1; } if (!ps4link_accept_pkt(ps4LinkGetValue(FILEIO_SOCK), recv_packet, sizeof(ps4link_pkt_dread_rly), PS4LINK_READDIR_RLY)) { debugNetPrintf(DEBUG,"[PS4LINK] ps4link_read_dir: did not receive OPENDIR_RLY\n"); return -1; } dirrly = (ps4link_pkt_dread_rly *)recv_packet; debugNetPrintf(DEBUG,"[PS4LINK] dir read reply received (ret %d)\n", sceNetNtohl(dirrly->retval)); dirent = (struct dirent *) dir; strncpy(dirent->d_name,dirrly->name,256); dirent->d_type=dirrly->type; return sceNetNtohl(dirrly->retval); }
int psp2link_commands_thread(SceSize args, void *argp) { struct SceNetSockaddrIn serveraddr; struct SceNetSockaddrIn remote_addr; int ret; int len; unsigned int addrlen; unsigned int cmd; psp2link_pkt_hdr *header; debugNetPrintf(DEBUG,"[PSP2LINK] Command Thread Started.\n" ); configuration->psp2link_commands_sock = sceNetSocket("commands_server_sock",SCE_NET_AF_INET, SCE_NET_SOCK_DGRAM, SCE_NET_IPPROTO_UDP); if (psp2LinkGetValue(COMMANDS_SOCK) >=0) { debugNetPrintf(DEBUG,"[PSP2LINK] Created psp2link_commands_sock: %d\n", psp2LinkGetValue(COMMANDS_SOCK)); } else { debugNetPrintf(DEBUG,"[PSP2LINK] Error creating socket psp2link_commands_sock 0x%08X\n", psp2LinkGetValue(COMMANDS_SOCK)); psp2LinkFinish(); return -1; } /* Fill the server's address */ memset(&serveraddr, 0, sizeof serveraddr); serveraddr.sin_family = SCE_NET_AF_INET; serveraddr.sin_addr.s_addr = sceNetHtonl(SCE_NET_INADDR_ANY); serveraddr.sin_port = sceNetHtons(psp2LinkGetValue(COMMANDS_PORT)); ret = sceNetBind(psp2LinkGetValue(COMMANDS_SOCK), (SceNetSockaddr *)&serveraddr, sizeof(serveraddr)); if (ret < 0) { debugNetPrintf(DEBUG,"[PSP2LINK] command listener sceNetBind error: 0x%08X\n", ret); sceNetSocketClose(psp2LinkGetValue(COMMANDS_SOCK)); psp2LinkFinish(); return -1; } // Do tha thing debugNetPrintf(DEBUG,"[PSP2LINK] Command listener waiting for commands...\n"); while(psp2LinkGetValue(CMDSIO_ACTIVE)) { addrlen = sizeof(remote_addr); //wait for new command len = sceNetRecvfrom(psp2LinkGetValue(COMMANDS_SOCK), &recvbuf[0], BUF_SIZE, 0, (struct SceNetSockaddr *)&remote_addr,&addrlen); debugNetPrintf(DEBUG,"[PSP2LINK] commands listener received packet size (%d)\n", len); if (len < 0) { debugNetPrintf(DEBUG,"[PSP2LINK] commands listener recvfrom size error (%d)\n", len); continue; } if (len < sizeof(psp2link_pkt_hdr)) { debugNetPrintf(DEBUG,"[PSP2LINK] commands listener recvfrom header size error (%d)\n", len); continue; } header = (psp2link_pkt_hdr *)recvbuf; cmd = sceNetHtonl(header->cmd); switch (cmd) { case PSP2LINK_EXECELF_CMD: psp2LinkCmdExecElf((psp2link_pkt_exec_cmd *)recvbuf); break; case PSP2LINK_EXECSPRX_CMD: psp2LinkCmdExecSprx((psp2link_pkt_exec_cmd *)recvbuf); break; case PSP2LINK_EXIT_CMD: psp2LinkCmdExit((psp2link_pkt_exec_cmd *)recvbuf); break; default: debugNetPrintf(DEBUG,"[PSP2LINK] Unknown command received\n"); break; } debugNetPrintf(DEBUG,"[PSP2LINK] commands listener waiting for next command\n"); } debugNetPrintf(DEBUG,"[PSP2LINK] exit commands listener thread\n"); if(psp2LinkGetValue(COMMANDS_SOCK)) { debugNetPrintf(DEBUG,"[PSP2LINK] closing server_commands_sock\n"); sceNetSocketClose(psp2LinkGetValue(COMMANDS_SOCK)); configuration->psp2link_commands_sock=-1; } sceKernelExitDeleteThread(0); return 0; }
void *ps4link_requests_thread(void * args) { int ret; struct sockaddr_in serveraddr; ps4link_requests_connected=0; /* Create server socket */ configuration->ps4link_requests_sock = sceNetSocket("requests_server_sock",AF_INET,SOCK_STREAM,0); if(ps4LinkGetValue(REQUESTS_SOCK)>=0) { debugNetPrintf(DEBUG,"[PS4LINK] Created ps4link_requests_sock: %d\n", ps4LinkGetValue(REQUESTS_SOCK)); } /* Fill the server's address */ serveraddr.sin_len = 16; serveraddr.sin_family = 2; serveraddr.sin_addr.s_addr = sceNetHtonl(INADDR_ANY); serveraddr.sin_port = sceNetHtons(ps4LinkGetValue(REQUESTS_PORT)); memset(serveraddr.sin_zero, 0, sizeof(serveraddr.sin_zero)); /* Bind the server's address to the socket */ ret = sceNetBind(ps4LinkGetValue(REQUESTS_SOCK), (struct sockaddr *)&serveraddr, sizeof(serveraddr)); if(ret<0) { debugNetPrintf(DEBUG,"[PS4LINK] sceNetBind error: 0x%08X\n", ret); sceNetSocketClose(ps4LinkGetValue(REQUESTS_SOCK)); return NULL; } debugNetPrintf(DEBUG,"[PS4LINK] bind to ps4link_requests_sock done\n"); /* Start listening */ ret = sceNetListen(ps4LinkGetValue(REQUESTS_SOCK), 5); if(ret<0) { debugNetPrintf(DEBUG,"[PS4LINK] sceNetListen error: 0x%08X\n", ret); sceNetSocketClose(ps4LinkGetValue(REQUESTS_SOCK)); return NULL; } debugNetPrintf(DEBUG,"[PS4LINK] Ready for connection %d\n", ps4LinkGetValue(FILEIO_ACTIVE)); while(ps4LinkGetValue(FILEIO_ACTIVE)) { debugNetPrintf(DEBUG,"[PS4LINK] Waiting for connection\n", ret); /* Accept clients */ struct sockaddr_in clientaddr; int client_sock; unsigned int addrlen = sizeof(clientaddr); client_sock = sceNetAccept(ps4LinkGetValue(REQUESTS_SOCK), (struct sockaddr *)&clientaddr, &addrlen); if (client_sock < 0) { debugNetPrintf(DEBUG,"[PS4LINK] sceNetAccept error (0x%08X)\n", client_sock); continue; } /* Get the client's IP address */ remote_pc_addr = clientaddr.sin_addr.s_addr; char remote_ip[16]; sceNetInetNtop(AF_INET,&clientaddr.sin_addr.s_addr,remote_ip,sizeof(remote_ip)); debugNetPrintf(DEBUG,"[PS4LINK] Client connected from %s port: %i\n ",remote_ip, clientaddr.sin_port); if (ps4LinkGetValue(FILEIO_SOCK) > 0) { debugNetPrintf(DEBUG,"[PS4LINK] Client reconnected\n"); // sceNetSocketClose(ps4LinkGetValue(FILEIO_SOCK)); } configuration->ps4link_fileio_sock = client_sock; ps4link_requests_connected=1; debugNetPrintf(DEBUG,"[PS4LINK] sock ps4link_fileio set %d connected %d\n",ps4LinkGetValue(FILEIO_SOCK),ps4link_requests_connected); } debugNetPrintf(DEBUG,"[PS4LINK] exit thread requests\n"); if(ps4LinkGetValue(FILEIO_SOCK)) { debugNetPrintf(DEBUG,"[PS4LINK] closing fileio_sock\n"); sceNetSocketClose(ps4LinkGetValue(FILEIO_SOCK)); configuration->ps4link_fileio_sock=-1; } if(ps4LinkGetValue(REQUESTS_SOCK)) { debugNetPrintf(DEBUG,"[PS4LINK] closing server_request_sock\n"); sceNetSocketClose(ps4LinkGetValue(REQUESTS_SOCK)); configuration->ps4link_requests_sock=-1; } ps4link_requests_connected=0; //sceKernelExitDeleteThread(0); return NULL; }
int ps4LinkWrite(int fd, const void *data, size_t size) { ps4link_pkt_write_req *writecmd; ps4link_pkt_file_rly *writerly; int hlen; int writtenbytes; int nbytes; int retval; if (ps4LinkGetValue(FILEIO_SOCK) < 0) { return -1; } debugNetPrintf(DEBUG,"[PS4LINK] file write req (fd: %d)\n", fd); writecmd = (ps4link_pkt_write_req *)&send_packet[0]; writerly = (ps4link_pkt_file_rly *)&recv_packet[0]; hlen = (unsigned short)sizeof(ps4link_pkt_write_req); writecmd->cmd = sceNetHtonl(PS4LINK_WRITE_CMD); writecmd->len = sceNetHtons(hlen); writecmd->fd = sceNetHtonl(fd); // Divide the write request writtenbytes = 0; while (writtenbytes < size) { if ((size - writtenbytes) > PS4LINK_MAX_WRITE_SEGMENT) { // Need to split in several read reqs nbytes = PS4LINK_MAX_READ_SEGMENT; } else { nbytes = size - writtenbytes; } writecmd->nbytes = sceNetHtonl(nbytes); #ifdef ZEROCOPY /* Send the packet header. */ if (ps4link_send(ps4LinkGetValue(FILEIO_SOCK), writecmd, hlen, MSG_DONTWAIT) < 0) return -1; /* Send the write() data. */ if (ps4link_send(ps4LinkGetValue(FILEIO_SOCK), &data[writtenbytes], nbytes, MSG_DONTWAIT) < 0) return -1; #else // Copy data to the acutal packet memcpy(&send_packet[sizeof(ps4link_pkt_write_req)], &data[writtenbytes],nbytes); if (ps4link_send(ps4LinkGetValue(FILEIO_SOCK), writecmd, hlen + nbytes, MSG_DONTWAIT) < 0) return -1; #endif // Get reply if(!ps4link_accept_pkt(ps4LinkGetValue(FILEIO_SOCK), (char *)writerly, sizeof(ps4link_pkt_file_rly), PS4LINK_WRITE_RLY)) { debugNetPrintf(DEBUG,"[PS4LINK] ps4link_write_file: " "did not receive PS4LINK_WRITE_RLY\n"); return -1; } retval = sceNetNtohl(writerly->retval); debugNetPrintf(DEBUG,"[PS4LINK] wrote %d bytes (asked for %d)\n", retval, nbytes); if (retval < 0) { // Error debugNetPrintf(DEBUG,"[PS4LINK] ps4link_write_file: received error on write req (%d)\n",retval); return retval; } writtenbytes += retval; if (retval < nbytes) { // EOF? break; } } return writtenbytes; }
int ps4LinkRead(int fd, void *data, size_t size) { int readbytes; int nbytes; int i; ps4link_pkt_read_req *readcmd; ps4link_pkt_read_rly *readrly; if (ps4LinkGetValue(FILEIO_SOCK) < 0) { return -1; } readcmd = (ps4link_pkt_read_req *)&send_packet[0]; readrly = (ps4link_pkt_read_rly *)&recv_packet[0]; readbytes = 0; readcmd->cmd = sceNetHtonl(PS4LINK_READ_CMD); readcmd->len = sceNetHtons((unsigned short)sizeof(ps4link_pkt_read_req)); readcmd->fd = sceNetHtonl(fd); readbytes = 0; /*if (size < 0) { debugNetPrintf(DEBUG,"[PS4LINK] ps4link_read_file: illegal req!! (whish to read < 0 bytes!)\n"); return -1; }*/ readcmd->nbytes = sceNetHtonl(size); i = ps4link_send(ps4LinkGetValue(FILEIO_SOCK), readcmd, sizeof(ps4link_pkt_read_req), MSG_DONTWAIT); if (i<0) { debugNetPrintf(DEBUG,"[PS4LINK] ps4link_file: ps4link_read_file: send failed (%d)\n", i); return -1; } if(!ps4link_accept_pkt(ps4LinkGetValue(FILEIO_SOCK), (char *)readrly, sizeof(ps4link_pkt_read_rly), PS4LINK_READ_RLY)) { debugNetPrintf(DEBUG,"[PS4LINK] ps4link_read_file: " "did not receive PS4LINK_READ_RLY\n"); return -1; } nbytes = sceNetNtohl(readrly->nbytes); debugNetPrintf(DEBUG,"[PS4LINK] ps4link_read_file: Reply said there's %d bytes to read " "(wanted %d)\n", nbytes, size); // Now read the actual file data divide in chunk int numread=nbytes/PACKET_MAXSIZE; int lastread=nbytes%PACKET_MAXSIZE; int j; for(j=0;j<numread;j++) { if(j<numread-1) { i = ps4link_recv_bytes(ps4LinkGetValue(FILEIO_SOCK), data+j*PACKET_MAXSIZE, PACKET_MAXSIZE); } else { i = ps4link_recv_bytes(ps4LinkGetValue(FILEIO_SOCK), data+j*PACKET_MAXSIZE, PACKET_MAXSIZE+lastread); } if (i < 0) { debugNetPrintf(DEBUG,"[PS4LINK] ps4link_read_file, data read error\n"); return -1; } debugNetPrintf(DEBUG,"[PS4LINK] ps4link_read_file: chunk %d readed %d\n", j,i); } return nbytes; }
static int server_thread(SceSize args, void *argp) { int ret; UNUSED(ret); SceNetSockaddrIn serveraddr; DEBUG("Server thread started!\n"); /* Create server socket */ server_sockfd = sceNetSocket("FTPVita_server_sock", PSP2_NET_AF_INET, PSP2_NET_SOCK_STREAM, 0); DEBUG("Server socket fd: %d\n", server_sockfd); /* Fill the server's address */ serveraddr.sin_family = PSP2_NET_AF_INET; serveraddr.sin_addr.s_addr = sceNetHtonl(PSP2_NET_INADDR_ANY); serveraddr.sin_port = sceNetHtons(FTP_PORT); /* Bind the server's address to the socket */ ret = sceNetBind(server_sockfd, (SceNetSockaddr *)&serveraddr, sizeof(serveraddr)); DEBUG("sceNetBind(): 0x%08X\n", ret); /* Start listening */ ret = sceNetListen(server_sockfd, 128); DEBUG("sceNetListen(): 0x%08X\n", ret); while (1) { /* Accept clients */ SceNetSockaddrIn clientaddr; int client_sockfd; unsigned int addrlen = sizeof(clientaddr); DEBUG("Waiting for incoming connections...\n"); client_sockfd = sceNetAccept(server_sockfd, (SceNetSockaddr *)&clientaddr, &addrlen); if (client_sockfd >= 0) { DEBUG("New connection, client fd: 0x%08X\n", client_sockfd); /* Get the client's IP address */ char remote_ip[16]; sceNetInetNtop(PSP2_NET_AF_INET, &clientaddr.sin_addr.s_addr, remote_ip, sizeof(remote_ip)); INFO("Client %i connected, IP: %s port: %i\n", number_clients, remote_ip, clientaddr.sin_port); /* Create a new thread for the client */ char client_thread_name[64]; sprintf(client_thread_name, "FTPVita_client_%i_thread", number_clients); SceUID client_thid = sceKernelCreateThread( client_thread_name, client_thread, 0x10000100, 0x10000, 0, 0, NULL); DEBUG("Client %i thread UID: 0x%08X\n", number_clients, client_thid); /* Allocate the ClientInfo struct for the new client */ ClientInfo *client = malloc(sizeof(*client)); client->num = number_clients; client->thid = client_thid; client->ctrl_sockfd = client_sockfd; client->data_con_type = FTP_DATA_CONNECTION_NONE; sprintf(client->cur_path, "%s%s", FTP_DEFAULT_PREFIX, FTP_DEFAULT_PATH); memcpy(&client->addr, &clientaddr, sizeof(client->addr)); /* Add the new client to the client list */ client_list_add(client); /* Start the client thread */ sceKernelStartThread(client_thid, sizeof(*client), client); number_clients++; } else { /* if sceNetAccept returns < 0, it means that the listening * socket has been closed, this means that we want to * finish the server thread */ DEBUG("Server socket closed, 0x%08X\n", client_sockfd); break; } } DEBUG("Server thread exiting!\n"); sceKernelExitDeleteThread(0); return 0; }