-
-
Save mgood7123/0eaca5cdde08893a0e138852df693f95 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define COPY_TO_BUF(buf, obj_type, obj) memcpy(buf, obj, sizeof(obj_type)); buf += sizeof(obj_type) | |
#define COPY_FROM_BUF(buf, obj_type, obj) memcpy(obj, buf, sizeof(obj_type)); buf += sizeof(obj_type) | |
#ifdef _WIN32 | |
void store_buffer_socket(void** buffer, size_t * buffer_len, wl_miniobj * obj) { | |
*buffer_len = sizeof(uint16_t)*2; | |
*buffer_len += sizeof(WSAPROTOCOL_INFO); | |
*buffer = malloc(*buffer_len); | |
char * tmp = *buffer; | |
COPY_TO_BUF(tmp, uint16_t, &obj->type); | |
COPY_TO_BUF(tmp, uint16_t, &obj->version); | |
COPY_TO_BUF(tmp, WSAPROTOCOL_INFO, (WSAPROTOCOL_INFO*)obj->data); | |
} | |
void store_buffer_handle(void** buffer, size_t * buffer_len, wl_miniobj * obj) { | |
*buffer_len = sizeof(uint16_t)*2; | |
*buffer_len += sizeof(HANDLE); | |
*buffer = malloc(*buffer_len); | |
char * tmp = *buffer; | |
COPY_TO_BUF(tmp, uint16_t, &obj->type); | |
COPY_TO_BUF(tmp, uint16_t, &obj->version); | |
COPY_TO_BUF(tmp, HANDLE, (HANDLE*)obj->data); | |
} | |
#else | |
void store_buffer_fd(void** buffer, size_t * buffer_len, wl_miniobj * obj) { | |
*buffer_len = sizeof(uint16_t)*2; | |
*buffer_len += sizeof(uint32_t); | |
*buffer = malloc(*buffer_len); | |
char * tmp = *buffer; | |
COPY_TO_BUF(tmp, uint16_t, &obj->type); | |
COPY_TO_BUF(tmp, uint16_t, &obj->version); | |
COPY_TO_BUF(tmp, uint32_t, &obj->data); | |
} | |
#endif | |
void wl_posix_fd_transfer__add(wl_posix_fd_struct* s, wl_miniobj* obj) { | |
if (s->first == NULL) { | |
s->first = malloc(sizeof(wl_posix_fd_linked_list)); | |
s->last = s->first; | |
} else { | |
s->last->next = malloc(sizeof(wl_posix_fd_linked_list)); | |
s->last = s->last->next; | |
} | |
#ifdef _WIN32 | |
if (obj->type == wl_posix_type_socket) { | |
store_buffer_socket(&s->last->buffer, &s->last->buffer_len, obj); | |
} else { | |
store_buffer_handle(&s->last->buffer, &s->last->buffer_len, obj); | |
} | |
#else | |
store_buffer_fd(&s->last->buffer, &s->last->buffer_len, obj); | |
#endif | |
s->count++; | |
} | |
wl_posix_fd_struct * wl_posix_fd_transfer__prepare(void) { | |
wl_posix_fd_struct * data = (wl_posix_fd_struct *) calloc(1, sizeof(wl_posix_fd_struct)); | |
data->data = (wl_posix_transfer*) calloc(1, sizeof(wl_posix_transfer)); | |
wl_posix_transfer* transfer = (wl_posix_transfer*) data->data; | |
} | |
#ifndef _WIN32 | |
#define SEND_MSG(fd, msg, data) \ | |
do { \ | |
len = sendmsg(fd, msg, MSG_NOSIGNAL | MSG_DONTWAIT); \ | |
} while (len == -1 && errno == EINTR); \ | |
free(data); \ | |
if (len == -1) { \ | |
return -1; \ | |
} | |
#define RECV_MSG(fd, msg) \ | |
do { \ | |
len = recvmsg(fd, msg, MSG_NOSIGNAL | MSG_DONTWAIT); \ | |
} while (len == -1 && errno == EINTR); \ | |
if (len == -1) { \ | |
return -1; \ | |
} | |
#define SEND_FD(fd, fd_, iov, iov_len, CLEN) \ | |
{ \ | |
struct msghdr msg = {0}; \ | |
size_t clen; \ | |
char * data = malloc(sizeof(char)*CLEN); \ | |
struct cmsghdr *cmsg = (struct cmsghdr *) data; \ | |
cmsg->cmsg_level = SOL_SOCKET; \ | |
cmsg->cmsg_type = SCM_RIGHTS; \ | |
memcpy(CMSG_DATA(cmsg), fd_, sizeof(uint32_t)); \ | |
cmsg->cmsg_len = CMSG_LEN(1); \ | |
clen = cmsg->cmsg_len; \ | |
msg.msg_iov = iov; \ | |
msg.msg_iovlen = iov_len; \ | |
msg.msg_control = (clen > 0) ? cmsg : NULL; \ | |
msg.msg_controllen = clen; \ | |
SEND_MSG(fd, msg, data); \ | |
} | |
#define RECV_FD(fd, fd_) \ | |
{ | |
struct msghdr msg = {0}; \ | |
RECV_MSG(fd, &msg); \ | |
struct cmsghdr *cmsg; \ | |
size_t size; \ | |
for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; \ | |
cmsg = CMSG_NXTHDR(msg, cmsg)) { \ | |
if (cmsg->cmsg_level != SOL_SOCKET || \ | |
cmsg->cmsg_type != SCM_RIGHTS) \ | |
continue; \ | |
size = cmsg->cmsg_len - CMSG_LEN(0); \ | |
memcpy(fd_, CMSG_DATA(cmsg), sizeof(uint32_t)); \ | |
break; /* we only get 1 fd */ | |
} | |
} | |
#endif | |
int wl_posix_fd_transfer__send(wl_posix_fd_struct* s, wl_miniobj* socket, struct iovec* iov, int iov_len, size_t CLEN) { | |
int len = 0; | |
wl_posix_transfer* transfer = s->data; | |
#ifdef _WIN32 | |
if (!transfer->sent_iovec) { | |
if (!transfer->have_count) { | |
transfer->iovec_count = iov_len; | |
transfer->iovec_current_count = iov_len; | |
transfer->have_count = true; | |
} | |
if (!transfer->sent_iov_count) { | |
WL_SEND_DATA(socket, &iov_len, sizeof(int)); | |
transfer->sent_iov_count = true; | |
} | |
while(transfer->iovec_current_count != 0) { | |
if (!transfer->sent_iov_base) { | |
WL_SEND_DATA(socket, iov[transfer->iovec_current_count].iov_base, iov[transfer->iovec_current_count].iov_len); | |
transfer->sent_iov_base = true; | |
} | |
transfer->iovec_current_count--; | |
transfer->sent_iov_base = false; | |
} | |
transfer->sent_iovec = true; | |
} | |
if (!transfer->sent_count) { | |
WL_SEND_DATA(socket, &s->count, sizeof(int)); | |
transfer->sent_count = true; | |
transfer->current = s->first; | |
} | |
WL_SEND_DATA(socket, transfer->current->buffer, transfer->current->buffer_len); | |
#else | |
int fd = wl_posix_get_socket(socket); | |
if (!transfer->sent_count) { | |
WL_SEND_DATA(fd, &s->count, sizeof(int)); | |
transfer->sent_count = true; | |
transfer->current = s->first; | |
} | |
uint16_t type, version; | |
uint32_t handle; | |
COPY_FROM_BUF(transfer->current->buffer, uint16_t, &type); | |
COPY_FROM_BUF(transfer->current->buffer, uint16_t, &version); | |
COPY_FROM_BUF(transfer->current->buffer, uint32_t, handle); | |
WL_SEND_DATA(fd, &type, sizeof(uint16_t)); | |
WL_SEND_DATA(fd, &version, sizeof(uint16_t)); | |
SEND_FD(fd, handle, iov, iov_len, CLEN); | |
#endif | |
transfer->current = transfer->current->next; | |
transfer->complete = transfer->current == NULL; | |
return len; | |
} | |
int wl_posix_fd_transfer__recv(wl_posix_fd_struct* s, wl_miniobj* socket, struct iovec* iov, int iov_len, size_t CLEN) { | |
int len = 0; | |
wl_posix_transfer* transfer = s->data; | |
#ifdef _WIN32 | |
if (!transfer->recv_iovec) { | |
if (!transfer->recv_iov_count) { | |
WL_RECV_DATA(socket, &transfer->iovec_count, sizeof(int)); | |
transfer->iovec_current_count = transfer->iovec_count; | |
transfer->recv_iov_count = true; | |
if (iov_len != transfer->iovec_count) { | |
printf("iovec obtained possible incorrect len: given to function = %d, obtained from socket: %d\n", iov_len, transfer->iovec_count); | |
} | |
} | |
while(transfer->iovec_current_count != 0) { | |
if (!transfer->recv_iov_base) { | |
WL_RECV_DATA(socket, iov[transfer->iovec_current_count].iov_base, iov[transfer->iovec_current_count].iov_len); | |
transfer->recv_iov_base = true; | |
} | |
transfer->iovec_current_count--; | |
transfer->recv_iov_base = false; | |
} | |
transfer->recv_iovec = true; | |
} | |
if (!transfer->recv_count) { | |
WL_RECV_DATA(socket, &transfer->count, sizeof(int)); | |
transfer->recv_count = true; | |
transfer->buf = malloc(sizeof(wl_miniobj)*transfer->count); | |
transfer->buf_start = transfer->buf; | |
} | |
wl_miniobj obj; | |
WL_RECV_DATA(socket, &obj.type, sizeof(uint16_t)); | |
WL_RECV_DATA(socket, &obj.version, sizeof(uint16_t)); | |
if (obj.type == wl_posix_type_socket) { | |
WSAPROTOCOL_INFO p; | |
WL_RECV_DATA(socket, &p, sizeof(WSAPROTOCOL_INFO)); | |
obj.data = (SOCKET) WSASocket( | |
FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, | |
FROM_PROTOCOL_INFO, &p, 0, 0 | |
); | |
} else { | |
HANDLE h = NULL; | |
WL_RECV_DATA(socket, &h, sizeof(HANDLE)); | |
obj.data = (uint64_t) h; | |
} | |
COPY_TO_BUF(transfer->buf, wl_miniobj, &obj); | |
transfer->count--; | |
transfer->complete = transfer->count <= 0; | |
#else | |
int fd = wl_posix_get_socket(socket); | |
if (!transfer->recv_count) { | |
WL_RECV_DATA(fd, &transfer->count, sizeof(int)); | |
transfer->recv_count = true; | |
transfer->buf = malloc(sizeof(wl_miniobj)*transfer->count); | |
transfer->buf_start = transfer->buf; | |
} | |
wl_miniobj obj; | |
WL_RECV_DATA(fd, &obj.type, sizeof(uint16_t)); | |
WL_RECV_DATA(fd, &obj.version, sizeof(uint16_t)); | |
uint32_t h; | |
RECV_FD(fd, &h); | |
obj.data = (uint64_t) h; | |
COPY_TO_BUF(transfer->buf, wl_miniobj, &obj); | |
transfer->count--; | |
transfer->complete = transfer->count <= 0; | |
#endif | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct wl_posix_fd_linked_list { | |
void * buffer; | |
size_t buffer_len; | |
struct wl_posix_fd_linked_list * next; | |
}; | |
typedef struct wl_posix_fd_linked_list wl_posix_fd_linked_list; | |
typedef struct wl_posix_transfer { | |
bool complete; | |
int iovec_current_count; | |
int iovec_count; | |
bool have_count; | |
// send | |
bool sent_iovec; | |
bool sent_iov_count; | |
bool sent_iov_base; | |
bool sent_count; | |
wl_posix_fd_linked_list * current; | |
// recv | |
bool recv_iovec; | |
bool recv_iov_count; | |
bool recv_iov_base; | |
bool recv_count; | |
int count; | |
wl_miniobj * buf; | |
char * buf_start; | |
} wl_posix_transfer; | |
typedef struct wl_posix_fd_struct { | |
wl_posix_fd_linked_list * first; | |
wl_posix_fd_linked_list * last; | |
wl_posix_transfer* data; | |
int count; | |
} wl_posix_fd_struct; | |
wl_posix_fd_struct * wl_posix_fd_transfer__prepare(void); | |
void wl_posix_fd_transfer__add(wl_posix_fd_struct* s, wl_miniobj* obj); | |
int wl_posix_fd_transfer__send(wl_posix_fd_struct* s, wl_miniobj* socket, struct iovec* iov, int iov_len, size_t CLEN); | |
int wl_posix_fd_transfer__recv(wl_posix_fd_struct* s, wl_miniobj* socket, struct iovec* iov, int iov_len, size_t CLEN); | |
void wl_posix_fd_transfer__delete(wl_posix_fd_struct* s); | |
#ifdef _WIN32 | |
#define WL_SEND_DATA(socket, data, size) \ | |
do { \ | |
len = wl_syscall__send(socket, (char*)data, size, MSG_NOSIGNAL | MSG_DONTWAIT); \ | |
} while (len == SOCKET_ERROR && WSAGetLastError() == WSAEINTR); \ | |
if (len == SOCKET_ERROR) { \ | |
return -1; \ | |
} | |
#define WL_RECV_DATA(socket, data, size) \ | |
do { \ | |
len = wl_syscall__recv(socket, (char*)data, size, MSG_DONTWAIT); \ | |
} while (len == SOCKET_ERROR && WSAGetLastError() == WSAEINTR); \ | |
if (len == SOCKET_ERROR) { \ | |
return -1; \ | |
} | |
#else | |
#define WL_SEND_DATA(fd, data, size) \ | |
do { \ | |
len = send(fd, (char*)data, size, MSG_NOSIGNAL | MSG_DONTWAIT); \ | |
} while (len == -1 && errno == EINTR); \ | |
if (len == -1) { \ | |
return -1; \ | |
} | |
#define WL_RECV_DATA(fd, data, size) \ | |
do { \ | |
len = recv(fd, (char*)data, size, MSG_DONTWAIT); \ | |
} while (len == -1 && errno == EINTR); \ | |
if (len == -1) { \ | |
return -1; \ | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment