|
|
|
@ -1,20 +1,40 @@ |
|
|
|
// Eltex BoolLoader Application Provisioning Protocol Server
|
|
|
|
// Eltex BoolLoader Application Provisioning Protocol Server
|
|
|
|
#include <arpa/inet.h> |
|
|
|
#include <arpa/inet.h> |
|
|
|
|
|
|
|
#include <errno.h> |
|
|
|
#include <fcntl.h> |
|
|
|
#include <fcntl.h> |
|
|
|
|
|
|
|
#include <netinet/in.h> |
|
|
|
|
|
|
|
#include <stdbool.h> |
|
|
|
#include <stdio.h> |
|
|
|
#include <stdio.h> |
|
|
|
#include <stdlib.h> |
|
|
|
#include <stdlib.h> |
|
|
|
#include <string.h> |
|
|
|
#include <string.h> |
|
|
|
|
|
|
|
#include <sys/mman.h> |
|
|
|
#include <sys/socket.h> |
|
|
|
#include <sys/socket.h> |
|
|
|
#include <sys/stat.h> |
|
|
|
#include <sys/stat.h> |
|
|
|
|
|
|
|
#include <time.h> |
|
|
|
#include <unistd.h> |
|
|
|
#include <unistd.h> |
|
|
|
|
|
|
|
|
|
|
|
#include "eblapp.h" |
|
|
|
#include "eblapp.h" |
|
|
|
#include "ring_buffer.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define BUFFER_SIZE 20000 |
|
|
|
#define BUFFER_SIZE 20000 |
|
|
|
#define PORT 1069 |
|
|
|
#define PORT 1069 |
|
|
|
#define MAX_PACKET_SIZE 1400 |
|
|
|
#define MAX_PACKET_SIZE 1400 |
|
|
|
#define TIMEOUT 5 |
|
|
|
#define TIMEOUT 5 |
|
|
|
|
|
|
|
#define MAX_CLIENTS 10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct client |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
bool valid; |
|
|
|
|
|
|
|
struct sockaddr_in client_addr; |
|
|
|
|
|
|
|
socklen_t addr_len; |
|
|
|
|
|
|
|
size_t current_offset; |
|
|
|
|
|
|
|
size_t current_acked_byte; |
|
|
|
|
|
|
|
int fd; |
|
|
|
|
|
|
|
const uint8_t* file_data; |
|
|
|
|
|
|
|
size_t file_size; |
|
|
|
|
|
|
|
time_t last_time; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct client g_clients[MAX_CLIENTS]; |
|
|
|
|
|
|
|
|
|
|
|
void error(const char* msg) |
|
|
|
void error(const char* msg) |
|
|
|
{ |
|
|
|
{ |
|
|
|
@ -22,93 +42,81 @@ void error(const char* msg) |
|
|
|
exit(1); |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int main() |
|
|
|
struct client* lookup_client(struct sockaddr* client_addr, size_t addr_len) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int ret = 0; |
|
|
|
for(size_t i = 0; i < MAX_CLIENTS; i++) |
|
|
|
int sockfd, newsockfd; |
|
|
|
|
|
|
|
socklen_t clilen; |
|
|
|
|
|
|
|
struct sockaddr_in serv_addr, cli_addr; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sockfd = socket(AF_INET, SOCK_DGRAM, 0); |
|
|
|
|
|
|
|
if(sockfd < 0) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
error("ERROR opening socket"); |
|
|
|
if(g_clients[i].valid && g_clients[i].addr_len == addr_len && memcmp(&g_clients[i].client_addr, client_addr, addr_len) == 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return &g_clients[i]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
memset((char*)&serv_addr, 0, sizeof(serv_addr)); |
|
|
|
struct client* find_free_client_entry() |
|
|
|
serv_addr.sin_family = AF_INET; |
|
|
|
|
|
|
|
serv_addr.sin_addr.s_addr = INADDR_ANY; |
|
|
|
|
|
|
|
serv_addr.sin_port = htons(PORT); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) |
|
|
|
|
|
|
|
error("ERROR on binding"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
printf("Server started on port %d\n", PORT); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while(1) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
char buffer[MAX_PACKET_SIZE]; |
|
|
|
for(size_t i = 0; i < MAX_CLIENTS; i++) |
|
|
|
clilen = sizeof(cli_addr); |
|
|
|
|
|
|
|
int n = recvfrom(sockfd, buffer, MAX_PACKET_SIZE, 0, (struct sockaddr*)&cli_addr, &clilen); |
|
|
|
|
|
|
|
if(n < 0) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
error("ERROR reading from socket"); |
|
|
|
if(!g_clients[i].valid) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return &g_clients[i]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct Eblapp_request* request = (struct Eblapp_request*)buffer; |
|
|
|
void delete_client(struct client* client) |
|
|
|
if(request->opcode == EBLAPP_REQUEST_FILE) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
size_t current_acked_byte = 0; |
|
|
|
munmap((void*)client->file_data, client->file_size); |
|
|
|
|
|
|
|
close(client->fd); |
|
|
|
|
|
|
|
client->valid = false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct ring_buffer* ring_buffer = NULL; |
|
|
|
int init_client(struct client* client_data, struct sockaddr_in* client_addr, socklen_t addr_len, const char* filename) |
|
|
|
if(ring_buffer__init(&ring_buffer, BUFFER_SIZE)) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
error("ring_buffer__init() failed"); |
|
|
|
int ret = 0; |
|
|
|
} |
|
|
|
|
|
|
|
struct stat st = {}; |
|
|
|
struct stat st = {}; |
|
|
|
char filename[256] = {}; |
|
|
|
|
|
|
|
uint32_t current_offset = 0; |
|
|
|
|
|
|
|
struct Eblapp_request* request = (struct Eblapp_request*)buffer; |
|
|
|
|
|
|
|
memcpy(filename, request->filename, request->filename_size); |
|
|
|
|
|
|
|
printf("Request file: %s\n", filename); |
|
|
|
printf("Request file: %s\n", filename); |
|
|
|
ret = stat(filename, &st); |
|
|
|
ret = stat(filename, &st); |
|
|
|
if(ret) |
|
|
|
if(ret) |
|
|
|
{ |
|
|
|
{ |
|
|
|
printf("stat failed(): %d", ret); |
|
|
|
printf("stat failed(): %d", ret); |
|
|
|
break; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int fd = open(filename, O_RDONLY); |
|
|
|
int fd = open(filename, O_RDONLY); |
|
|
|
if(fd < 0) |
|
|
|
if(fd < 0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
printf("File not found: %s\n", filename); |
|
|
|
printf("File not found: %s\n", filename); |
|
|
|
continue; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const uint8_t* const file_data = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); |
|
|
|
while(1) |
|
|
|
if(file_data == MAP_FAILED) |
|
|
|
{ |
|
|
|
|
|
|
|
size_t space_left = 0; |
|
|
|
|
|
|
|
size_t bytes_left = 0; |
|
|
|
|
|
|
|
ring_buffer__get_free_bytes(ring_buffer, &space_left); |
|
|
|
|
|
|
|
while(space_left) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
size_t toread = space_left > MAX_PACKET_SIZE ? MAX_PACKET_SIZE : space_left; |
|
|
|
printf("Unable to mmap file: %d\n", errno); |
|
|
|
int bytes_read = read(fd, buffer, toread); |
|
|
|
return ret; |
|
|
|
if(bytes_read <= 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(ring_buffer__write(ring_buffer, buffer, bytes_read) < 0) |
|
|
|
memcpy(&client_data->client_addr, client_addr, sizeof(*client_addr)); |
|
|
|
{ |
|
|
|
client_data->addr_len = addr_len; |
|
|
|
error("ring_buffer__write() failed"); |
|
|
|
client_data->fd = fd; |
|
|
|
} |
|
|
|
client_data->file_data = file_data; |
|
|
|
|
|
|
|
client_data->file_size = st.st_size; |
|
|
|
|
|
|
|
client_data->last_time = time(NULL); |
|
|
|
|
|
|
|
client_data->current_acked_byte = 0; |
|
|
|
|
|
|
|
client_data->current_offset = 0; |
|
|
|
|
|
|
|
client_data->valid = true; |
|
|
|
|
|
|
|
|
|
|
|
ring_buffer__get_free_bytes(ring_buffer, &space_left); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ring_buffer__get_unread_bytes(ring_buffer, &bytes_left); |
|
|
|
void client_loop(int sockfd, struct client* client_data) |
|
|
|
while(bytes_left) |
|
|
|
{ |
|
|
|
|
|
|
|
uint8_t buffer[MAX_PACKET_SIZE]; |
|
|
|
|
|
|
|
size_t bytes_left = client_data->file_size - client_data->current_offset; |
|
|
|
|
|
|
|
size_t unacked = client_data->current_offset - client_data->current_acked_byte; |
|
|
|
|
|
|
|
while(bytes_left && unacked < BUFFER_SIZE) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct Eblapp_transfer_data* data = (struct Eblapp_transfer_data*)buffer; |
|
|
|
struct Eblapp_transfer_data* data = (struct Eblapp_transfer_data*)buffer; |
|
|
|
size_t toread = bytes_left; |
|
|
|
size_t toread = bytes_left; |
|
|
|
@ -116,101 +124,181 @@ int main() |
|
|
|
{ |
|
|
|
{ |
|
|
|
toread = MAX_PACKET_SIZE - 8; |
|
|
|
toread = MAX_PACKET_SIZE - 8; |
|
|
|
} |
|
|
|
} |
|
|
|
if (st.st_size - current_offset > 256) |
|
|
|
if(client_data->file_size - client_data->current_offset > 256) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Keep destination nice and aligned
|
|
|
|
// Keep destination nice and aligned
|
|
|
|
toread &= ~(0x0f); |
|
|
|
toread &= ~(0x0f); |
|
|
|
if(toread == 0) |
|
|
|
if(toread == 0) |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
if(ring_buffer__read(ring_buffer, buffer + 8, &toread) < 0) |
|
|
|
// printf("bytes_left: %zu, current_offset: %zu\n", bytes_left, client_data->current_offset);
|
|
|
|
{ |
|
|
|
memcpy(buffer + 8, &client_data->file_data[client_data->current_offset], toread); |
|
|
|
perror("ring_buffer__read() failed"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data->opcode = EBLAPP_TRANSFER_DATA; |
|
|
|
data->opcode = EBLAPP_TRANSFER_DATA; |
|
|
|
data->block_start = current_offset; |
|
|
|
data->block_start = client_data->current_offset; |
|
|
|
int n = sendto(sockfd, buffer, toread + sizeof(*data), 0, (struct sockaddr*)&cli_addr, clilen); |
|
|
|
int n = sendto(sockfd, buffer, toread + sizeof(*data), 0, (struct sockaddr*)&client_data->client_addr, client_data->addr_len); |
|
|
|
if(n < 0) |
|
|
|
if(n < 0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
error("ERROR sending packet"); |
|
|
|
error("ERROR sending packet"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
current_offset += (n - 8); |
|
|
|
client_data->current_offset += toread; |
|
|
|
ring_buffer__get_unread_bytes(ring_buffer, &bytes_left); |
|
|
|
bytes_left -= toread; |
|
|
|
|
|
|
|
unacked += toread; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
time_t now = time(NULL); |
|
|
|
|
|
|
|
if(now - client_data->last_time > TIMEOUT) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
printf("!ack recevied: %zu/%zu/(%zu)\n", client_data->current_acked_byte, client_data->current_offset, |
|
|
|
|
|
|
|
client_data->current_offset - client_data->current_acked_byte); |
|
|
|
|
|
|
|
client_data->current_offset = client_data->current_acked_byte; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int client_ack(int sockfd, struct client* client_data, size_t acked_byte, bool* done) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if(acked_byte >= client_data->file_size) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
printf("Transfer done\n"); |
|
|
|
|
|
|
|
*done = true; |
|
|
|
|
|
|
|
struct Eblapp_transfer_end transfer_end = {}; |
|
|
|
|
|
|
|
transfer_end.opcode = EBLAPP_TRANSFER_END; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int n = sendto(sockfd, &transfer_end, sizeof(transfer_end), 0, (struct sockaddr*)&client_data->client_addr, client_data->addr_len); |
|
|
|
|
|
|
|
if(n < 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
error("ERROR sending transfer end"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
printf("sent %d\n", n); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(acked_byte >= client_data->current_acked_byte) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
size_t delta = acked_byte - client_data->current_acked_byte; |
|
|
|
|
|
|
|
client_data->current_acked_byte = acked_byte; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
client_data->last_time = time(NULL); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
client_loop(sockfd, client_data); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int client_wtf(int sockfd, struct client* client_data, size_t acked_byte) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
client_data->current_offset = client_data->current_acked_byte; |
|
|
|
|
|
|
|
client_data->last_time = time(NULL); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
client_loop(sockfd, client_data); |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int main() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int ret = 0; |
|
|
|
|
|
|
|
int sockfd, newsockfd; |
|
|
|
|
|
|
|
socklen_t clilen; |
|
|
|
|
|
|
|
struct sockaddr_in serv_addr, cli_addr; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sockfd = socket(AF_INET, SOCK_DGRAM, 0); |
|
|
|
|
|
|
|
if(sockfd < 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
error("ERROR opening socket"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memset((char*)&serv_addr, 0, sizeof(serv_addr)); |
|
|
|
|
|
|
|
serv_addr.sin_family = AF_INET; |
|
|
|
|
|
|
|
serv_addr.sin_addr.s_addr = INADDR_ANY; |
|
|
|
|
|
|
|
serv_addr.sin_port = htons(PORT); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) |
|
|
|
|
|
|
|
error("ERROR on binding"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
printf("Server started on port %d\n", PORT); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while(1) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
char buffer[MAX_PACKET_SIZE]; |
|
|
|
|
|
|
|
clilen = sizeof(cli_addr); |
|
|
|
|
|
|
|
|
|
|
|
// Wait for ACKs
|
|
|
|
|
|
|
|
fd_set readfds; |
|
|
|
fd_set readfds; |
|
|
|
struct timeval tv; |
|
|
|
struct timeval tv; |
|
|
|
int ack_received = 0; |
|
|
|
int ack_received = 0; |
|
|
|
|
|
|
|
|
|
|
|
FD_ZERO(&readfds); |
|
|
|
FD_ZERO(&readfds); |
|
|
|
FD_SET(sockfd, &readfds); |
|
|
|
FD_SET(sockfd, &readfds); |
|
|
|
tv.tv_sec = TIMEOUT; |
|
|
|
tv.tv_sec = 0; |
|
|
|
tv.tv_usec = 0; |
|
|
|
tv.tv_usec = 500000; |
|
|
|
|
|
|
|
|
|
|
|
int rv = select(sockfd + 1, &readfds, NULL, NULL, &tv); |
|
|
|
int rv = select(sockfd + 1, &readfds, NULL, NULL, &tv); |
|
|
|
if(rv > 0) |
|
|
|
if(rv > 0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
n = recvfrom(sockfd, buffer, MAX_PACKET_SIZE, 0, (struct sockaddr*)&cli_addr, &clilen); |
|
|
|
int n = recvfrom(sockfd, buffer, MAX_PACKET_SIZE, 0, (struct sockaddr*)&cli_addr, &clilen); |
|
|
|
if(n >= 4) |
|
|
|
if(n < 0) |
|
|
|
{ |
|
|
|
|
|
|
|
struct Eblapp_ack* ack_packet = (struct Eblapp_ack*)buffer; |
|
|
|
|
|
|
|
if(ack_packet->opcode == EBLAPP_ACK) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
uint32_t acked_byte = ack_packet->ack_byte; |
|
|
|
|
|
|
|
if(acked_byte >= st.st_size) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
printf("Transfer done\n"); |
|
|
|
error("ERROR reading from socket"); |
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(acked_byte >= current_acked_byte) |
|
|
|
struct Eblapp_request* request = (struct Eblapp_request*)buffer; |
|
|
|
|
|
|
|
if(request->opcode == EBLAPP_REQUEST_FILE) |
|
|
|
{ |
|
|
|
{ |
|
|
|
size_t delta = acked_byte - current_acked_byte; |
|
|
|
size_t current_acked_byte = 0; |
|
|
|
ring_buffer__ack(ring_buffer, delta); |
|
|
|
uint32_t current_offset = 0; |
|
|
|
current_acked_byte = acked_byte; |
|
|
|
|
|
|
|
} |
|
|
|
char filename[256] = {}; |
|
|
|
ack_received = 1; |
|
|
|
struct Eblapp_request* request = (struct Eblapp_request*)buffer; |
|
|
|
|
|
|
|
memcpy(filename, request->filename, request->filename_size); |
|
|
|
|
|
|
|
struct client* client_data = find_free_client_entry(); |
|
|
|
|
|
|
|
if(!client_data) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
printf("No free clients entry\n"); |
|
|
|
|
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
else if(ack_packet->opcode == EBLAPP_WTF) |
|
|
|
if(init_client(client_data, &cli_addr, clilen, filename)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
printf("Wtf received: %d/%d\n", ack_packet->ack_byte, current_acked_byte); |
|
|
|
error("Unable to init client"); |
|
|
|
ack_received = 0; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
client_loop(sockfd, client_data); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
else if(request->opcode == EBLAPP_ACK) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct Eblapp_ack* ack_packet = (struct Eblapp_ack*)buffer; |
|
|
|
|
|
|
|
bool done = false; |
|
|
|
|
|
|
|
struct client* client = lookup_client((struct sockaddr*)&cli_addr, clilen); |
|
|
|
|
|
|
|
if(!client) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
printf("Unknown client packet\n"); |
|
|
|
|
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
client_ack(sockfd, client, ack_packet->ack_byte, &done); |
|
|
|
if(!ack_received) |
|
|
|
if(done) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Timeout, resend all packets in window
|
|
|
|
delete_client(client); |
|
|
|
printf("!ack recevied: %d/%d/(%d)\n", current_acked_byte, current_offset, current_offset - current_acked_byte); |
|
|
|
|
|
|
|
ring_buffer__unread(ring_buffer, current_offset - current_acked_byte); |
|
|
|
|
|
|
|
current_offset = current_acked_byte; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
else if(request->opcode == EBLAPP_WTF) |
|
|
|
close(fd); |
|
|
|
|
|
|
|
printf("File %s sent successfully\n", filename); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
struct Eblapp_transfer_end transfer_end = {}; |
|
|
|
struct Eblapp_ack* ack_packet = (struct Eblapp_ack*)buffer; |
|
|
|
transfer_end.opcode = EBLAPP_TRANSFER_END; |
|
|
|
struct client* client = lookup_client((struct sockaddr*)&cli_addr, clilen); |
|
|
|
|
|
|
|
if(!client) |
|
|
|
int n = sendto(sockfd, &transfer_end, sizeof(transfer_end), 0, (struct sockaddr*)&cli_addr, clilen); |
|
|
|
|
|
|
|
if(n < 0) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
error("ERROR sending transfer end"); |
|
|
|
printf("Unknown client packet\n"); |
|
|
|
|
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
printf("Wtf received: %d/%d\n", ack_packet->ack_byte, client->current_acked_byte); |
|
|
|
{ |
|
|
|
client_wtf(sockfd, client, ack_packet->ack_byte); |
|
|
|
printf("sent %d\n", n); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
for(size_t i = 0; i < MAX_CLIENTS; i++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if(g_clients[i].valid) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
client_loop(sockfd, &g_clients[i]); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
close(sockfd); |
|
|
|
close(sockfd); |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|