Skip to content

Commit f4dbfca

Browse files
authored
net: do wii network transfers in blocks (#178)
1 parent 0d23455 commit f4dbfca

File tree

1 file changed

+83
-46
lines changed

1 file changed

+83
-46
lines changed

libogc/network_wii.c

Lines changed: 83 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ static u8 _net_error_code_map[] = {
234234
ETIMEDOUT,
235235
};
236236

237+
static const s32 maxblocksize = (NET_HEAP_SIZE/2);
237238
static volatile bool _init_busy = false;
238239
static volatile bool _init_abort = false;
239240
static vs32 _last_init_result = -ENETDOWN;
@@ -890,35 +891,50 @@ s32 net_sendto(s32 s, const void *data, s32 len, u32 flags, struct sockaddr *to,
890891

891892
if (net_ip_top_fd < 0) return -ENXIO;
892893
if (tolen > 28) return -EOVERFLOW;
893-
894-
message_buf = net_malloc(len);
894+
895+
s32 blockSize = len > maxblocksize ? maxblocksize : len;
896+
message_buf = net_malloc(blockSize);
895897
if (message_buf == NULL) {
896-
debug_printf("net_send: failed to alloc %d bytes\n", len);
898+
debug_printf("net_send: failed to alloc %d bytes\n", blockSize);
897899
return IPC_ENOMEM;
898900
}
901+
902+
for(ret = 0; ret < len;)
903+
{
904+
blockSize = len - ret;
905+
if(blockSize > maxblocksize)
906+
blockSize = maxblocksize;
907+
908+
debug_printf("net_sendto(%d, %p, %d, %d, %p, %d)\n", s, data+ret, blockSize, flags, to, tolen);
909+
if (to && to->sa_len != tolen) {
910+
debug_printf("warning: to->sa_len was %d, setting to %d\n", to->sa_len, tolen);
911+
to->sa_len = tolen;
912+
}
913+
914+
memset(params, 0, sizeof(struct sendto_params));
915+
memcpy(message_buf, data+ret, blockSize); // ensure message buf is aligned
916+
917+
params->socket = s;
918+
params->flags = flags;
919+
if (to) {
920+
params->has_destaddr = 1;
921+
memcpy(params->destaddr, to, to->sa_len);
922+
} else {
923+
params->has_destaddr = 0;
924+
}
899925

900-
debug_printf("net_sendto(%d, %p, %d, %d, %p, %d)\n", s, data, len, flags, to, tolen);
901-
902-
if (to && to->sa_len != tolen) {
903-
debug_printf("warning: to->sa_len was %d, setting to %d\n", to->sa_len, tolen);
904-
to->sa_len = tolen;
905-
}
906-
907-
memset(params, 0, sizeof(struct sendto_params));
908-
memcpy(message_buf, data, len); // ensure message buf is aligned
909-
910-
params->socket = s;
911-
params->flags = flags;
912-
if (to) {
913-
params->has_destaddr = 1;
914-
memcpy(params->destaddr, to, to->sa_len);
915-
} else {
916-
params->has_destaddr = 0;
926+
s32 sent = _net_convert_error(IOS_IoctlvFormat(__net_hid, net_ip_top_fd, IOCTLV_SO_SENDTO, "dd:", message_buf, blockSize, params, sizeof(struct sendto_params)));
927+
debug_printf("net_send retuned %d\n", sent);
928+
929+
if(sent <= 0)
930+
{
931+
ret = sent;
932+
break;
933+
}
934+
935+
ret += sent;
917936
}
918937

919-
ret = _net_convert_error(IOS_IoctlvFormat(__net_hid, net_ip_top_fd, IOCTLV_SO_SENDTO, "dd:", message_buf, len, params, sizeof(struct sendto_params)));
920-
debug_printf("net_send retuned %d\n", ret);
921-
922938
if(message_buf!=NULL) net_free(message_buf);
923939
return ret;
924940
}
@@ -941,35 +957,56 @@ s32 net_recvfrom(s32 s, void *mem, s32 len, u32 flags, struct sockaddr *from, so
941957
debug_printf("warning: from->sa_len was %d, setting to %d\n",from->sa_len, *fromlen);
942958
from->sa_len = *fromlen;
943959
}
944-
945-
message_buf = net_malloc(len);
960+
961+
s32 blockSize = len > maxblocksize ? maxblocksize : len;
962+
message_buf = net_malloc(blockSize);
946963
if (message_buf == NULL) {
947-
debug_printf("SORecv: failed to alloc %d bytes\n", len);
964+
debug_printf("SORecv: failed to alloc %d bytes\n", blockSize);
948965
return IPC_ENOMEM;
949966
}
950-
951-
debug_printf("net_recvfrom(%d, '%s', %d, %d, %p, %d)\n", s, (char *)mem, len, flags, from, fromlen?*fromlen:0);
952-
953-
memset(message_buf, 0, len);
954-
params[0] = s;
955-
params[1] = flags;
956-
957-
ret = _net_convert_error(IOS_IoctlvFormat(__net_hid, net_ip_top_fd, IOCTLV_SO_RECVFROM, "d:dd", params, 8, message_buf, len, from, (fromlen?*fromlen:0)));
958-
debug_printf("net_recvfrom returned %d\n", ret);
959-
960-
if (ret > 0) {
961-
if (ret > len) {
967+
968+
for(ret = 0; ret < len;)
969+
{
970+
blockSize = len - ret;
971+
if(blockSize > maxblocksize)
972+
blockSize = maxblocksize;
973+
974+
debug_printf("net_recvfrom(%d, '%s', %d, %d, %p, %d)\n", s, (char *)mem, blockSize, flags, from, fromlen?*fromlen:0);
975+
976+
memset(message_buf, 0, blockSize);
977+
params[0] = s;
978+
params[1] = flags;
979+
980+
s32 received = _net_convert_error(IOS_IoctlvFormat(__net_hid, net_ip_top_fd, IOCTLV_SO_RECVFROM, "d:dd", params, 8, message_buf, blockSize, from, (fromlen?*fromlen:0)));
981+
debug_printf("net_recvfrom returned %d\n", received);
982+
983+
//connection closed(0) or error(<0)
984+
if(received <= 0)
985+
{
986+
if (fromlen && from) *fromlen = from->sa_len;
987+
ret = received;
988+
break;
989+
}
990+
991+
//well something went wrong lol
992+
if(received > blockSize)
993+
{
962994
ret = -EOVERFLOW;
963-
goto done;
995+
break;
964996
}
965-
966-
memcpy(mem, message_buf, ret);
997+
998+
if (fromlen && from) *fromlen = from->sa_len;
999+
memcpy(mem+ret, message_buf, received);
1000+
ret += received;
1001+
1002+
//we got a partial read, so we break and report the partial read
1003+
if(received != blockSize)
1004+
break;
9671005
}
968-
969-
if (fromlen && from) *fromlen = from->sa_len;
970-
971-
done:
972-
if(message_buf!=NULL) net_free(message_buf);
1006+
1007+
if(message_buf!=NULL)
1008+
net_free(message_buf);
1009+
9731010
return ret;
9741011
}
9751012

0 commit comments

Comments
 (0)