/** * xrdp: A Remote Desktop Protocol server. * * Copyright (C) Jay Sorg 2004-2013 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * librdp tcp layer */ #include "rdp.h" /*****************************************************************************/ struct rdp_tcp *APP_CC rdp_tcp_create(struct rdp_iso *owner) { struct rdp_tcp *self; self = (struct rdp_tcp *)g_malloc(sizeof(struct rdp_tcp), 1); self->iso_layer = owner; return self; } /*****************************************************************************/ void APP_CC rdp_tcp_delete(struct rdp_tcp *self) { g_free(self); } /*****************************************************************************/ /* get out stream ready for data */ /* returns error */ int APP_CC rdp_tcp_init(struct rdp_tcp *self, struct stream *s) { init_stream(s, 8192); return 0; } /*****************************************************************************/ /* returns error */ int APP_CC rdp_tcp_recv(struct rdp_tcp *self, struct stream *s, int len) { int rcvd; DEBUG((" in rdp_tcp_recv will get %d bytes on sck %d", len, self->sck)); if (self->sck_closed) { DEBUG((" out rdp_tcp_recv error sck closed")); return 1; } init_stream(s, len); while (len > 0) { rcvd = g_tcp_recv(self->sck, s->end, len, 0); if (rcvd == -1) { if (g_tcp_last_error_would_block(self->sck)) { g_sck_can_recv(self->sck, 10); } else { self->sck_closed = 1; DEBUG((" out rdp_tcp_recv error unknown")); return 1; } } else if (rcvd == 0) { self->sck_closed = 1; DEBUG((" out rdp_tcp_recv error connection dropped")); return 1; } else { s->end += rcvd; len -= rcvd; } } return 0; } /*****************************************************************************/ /* returns error */ int APP_CC rdp_tcp_send(struct rdp_tcp *self, struct stream *s) { int len; int total; int sent; if (self->sck_closed) { DEBUG((" out rdp_tcp_send error sck closed")); return 1; } len = s->end - s->data; DEBUG((" in rdp_tcp_send will send %d bytes on sck %d", len, self->sck)); total = 0; while (total < len) { sent = g_tcp_send(self->sck, s->data + total, len - total, 0); if (sent == -1) { if (g_tcp_last_error_would_block(self->sck)) { g_tcp_can_send(self->sck, 10); } else { self->sck_closed = 1; DEBUG((" out rdp_tcp_send error unknown")); return 1; } } else if (sent == 0) { self->sck_closed = 1; DEBUG((" out rdp_tcp_send error connection dropped")); return 1; } else { total = total + sent; } } return 0; } /*****************************************************************************/ /* returns error */ int APP_CC rdp_tcp_connect(struct rdp_tcp *self, char *ip, char *port) { DEBUG((" in rdp_tcp_connect ip %s port %s", ip, port)); self->sck = g_tcp_socket(); if (self->sck < 0) return 1; if (g_tcp_connect(self->sck, ip, port) == 0) { g_tcp_set_non_blocking(self->sck); } else { DEBUG((" out rdp_tcp_connect error g_tcp_connect failed")); return 1; } DEBUG((" out rdp_tcp_connect")); return 0; } /*****************************************************************************/ /* returns error */ int APP_CC rdp_tcp_disconnect(struct rdp_tcp *self) { if (self->sck != 0) { g_tcp_close(self->sck); } self->sck = 0; return 0; }