summaryrefslogtreecommitdiffstats
path: root/common/trans.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/trans.c')
-rw-r--r--common/trans.c693
1 files changed, 367 insertions, 326 deletions
diff --git a/common/trans.c b/common/trans.c
index 6b762d00..c287d310 100644
--- a/common/trans.c
+++ b/common/trans.c
@@ -1,27 +1,22 @@
-/*
- Copyright (c) 2008-2010 Jay Sorg
-
- Permission is hereby granted, free of charge, to any person obtaining a
- copy of this software and associated documentation files (the "Software"),
- to deal in the Software without restriction, including without limitation
- the rights to use, copy, modify, merge, publish, distribute, sublicense,
- and/or sell copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- DEALINGS IN THE SOFTWARE.
-
- generic transport
-
-*/
+/**
+ * xrdp: A Remote Desktop Protocol server.
+ *
+ * Copyright (C) Jay Sorg 2004-2012
+ *
+ * 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.
+ *
+ * generic transport
+ */
#include "os_calls.h"
#include "trans.h"
@@ -29,394 +24,440 @@
#include "parse.h"
/*****************************************************************************/
-struct trans* APP_CC
+struct trans *APP_CC
trans_create(int mode, int in_size, int out_size)
{
- struct trans* self = (struct trans *)NULL;
-
- self = (struct trans*)g_malloc(sizeof(struct trans), 1);
- if (self != NULL) {
- make_stream(self->in_s);
- init_stream(self->in_s, in_size);
- make_stream(self->out_s);
- init_stream(self->out_s, out_size);
- self->mode = mode;
- }
- return self;
+ struct trans *self = (struct trans *)NULL;
+
+ self = (struct trans *)g_malloc(sizeof(struct trans), 1);
+
+ if (self != NULL)
+ {
+ make_stream(self->in_s);
+ init_stream(self->in_s, in_size);
+ make_stream(self->out_s);
+ init_stream(self->out_s, out_size);
+ self->mode = mode;
+ }
+
+ return self;
}
/*****************************************************************************/
void APP_CC
-trans_delete(struct trans* self)
+trans_delete(struct trans *self)
{
- if (self == 0)
- {
- return;
- }
- free_stream(self->in_s);
- free_stream(self->out_s);
- if (self->sck > 0) {
- g_tcp_close(self->sck);
- }
- self->sck = 0;
- if (self->listen_filename != 0)
- {
- g_file_delete(self->listen_filename);
- g_free(self->listen_filename);
- }
- g_free(self);
+ if (self == 0)
+ {
+ return;
+ }
+
+ free_stream(self->in_s);
+ free_stream(self->out_s);
+
+ if (self->sck > 0)
+ {
+ g_tcp_close(self->sck);
+ }
+
+ self->sck = 0;
+
+ if (self->listen_filename != 0)
+ {
+ g_file_delete(self->listen_filename);
+ g_free(self->listen_filename);
+ }
+
+ g_free(self);
}
/*****************************************************************************/
int APP_CC
-trans_get_wait_objs(struct trans* self, tbus* objs, int* count)
+trans_get_wait_objs(struct trans *self, tbus *objs, int *count)
{
- if (self == 0)
- {
- return 1;
- }
- if (self->status != TRANS_STATUS_UP)
- {
- return 1;
- }
- objs[*count] = self->sck;
- (*count)++;
- return 0;
+ if (self == 0)
+ {
+ return 1;
+ }
+
+ if (self->status != TRANS_STATUS_UP)
+ {
+ return 1;
+ }
+
+ objs[*count] = self->sck;
+ (*count)++;
+ return 0;
}
/*****************************************************************************/
int APP_CC
-trans_check_wait_objs(struct trans* self)
+trans_check_wait_objs(struct trans *self)
{
- tbus in_sck = (tbus)0;
- struct trans* in_trans = (struct trans *)NULL;
- int read_bytes = 0;
- int to_read = 0;
- int read_so_far = 0;
- int rv = 0;
-
- if (self == 0)
- {
- return 1;
- }
- if (self->status != TRANS_STATUS_UP)
- {
- return 1;
- }
- rv = 0;
- if (self->type1 == TRANS_TYPE_LISTENER) /* listening */
- {
- if (g_tcp_can_recv(self->sck, 0))
+ tbus in_sck = (tbus)0;
+ struct trans *in_trans = (struct trans *)NULL;
+ int read_bytes = 0;
+ int to_read = 0;
+ int read_so_far = 0;
+ int rv = 0;
+
+ if (self == 0)
{
- in_sck = g_tcp_accept(self->sck);
- if (in_sck == -1)
- {
- if (g_tcp_last_error_would_block(self->sck))
- {
- /* ok, but shouldn't happen */
- }
- else
- {
- /* error */
- self->status = TRANS_STATUS_DOWN;
- return 1;
- }
- }
- if (in_sck != -1)
- {
- if (self->trans_conn_in != 0) /* is function assigned */
+ return 1;
+ }
+
+ if (self->status != TRANS_STATUS_UP)
+ {
+ return 1;
+ }
+
+ rv = 0;
+
+ if (self->type1 == TRANS_TYPE_LISTENER) /* listening */
+ {
+ if (g_tcp_can_recv(self->sck, 0))
{
- in_trans = trans_create(self->mode, self->in_s->size,
- self->out_s->size);
- in_trans->sck = in_sck;
- in_trans->type1 = TRANS_TYPE_SERVER;
- in_trans->status = TRANS_STATUS_UP;
- if (self->trans_conn_in(self, in_trans) != 0)
- {
- trans_delete(in_trans);
- }
+ in_sck = g_tcp_accept(self->sck);
+
+ if (in_sck == -1)
+ {
+ if (g_tcp_last_error_would_block(self->sck))
+ {
+ /* ok, but shouldn't happen */
+ }
+ else
+ {
+ /* error */
+ self->status = TRANS_STATUS_DOWN;
+ return 1;
+ }
+ }
+
+ if (in_sck != -1)
+ {
+ if (self->trans_conn_in != 0) /* is function assigned */
+ {
+ in_trans = trans_create(self->mode, self->in_s->size,
+ self->out_s->size);
+ in_trans->sck = in_sck;
+ in_trans->type1 = TRANS_TYPE_SERVER;
+ in_trans->status = TRANS_STATUS_UP;
+
+ if (self->trans_conn_in(self, in_trans) != 0)
+ {
+ trans_delete(in_trans);
+ }
+ }
+ else
+ {
+ g_tcp_close(in_sck);
+ }
+ }
}
- else
+ }
+ else /* connected server or client (2 or 3) */
+ {
+ if (g_tcp_can_recv(self->sck, 0))
{
- g_tcp_close(in_sck);
+ read_so_far = (int)(self->in_s->end - self->in_s->data);
+ to_read = self->header_size - read_so_far;
+
+ if (to_read > 0)
+ {
+ read_bytes = g_tcp_recv(self->sck, self->in_s->end, to_read, 0);
+
+ if (read_bytes == -1)
+ {
+ if (g_tcp_last_error_would_block(self->sck))
+ {
+ /* ok, but shouldn't happen */
+ }
+ else
+ {
+ /* error */
+ self->status = TRANS_STATUS_DOWN;
+ return 1;
+ }
+ }
+ else if (read_bytes == 0)
+ {
+ /* error */
+ self->status = TRANS_STATUS_DOWN;
+ return 1;
+ }
+ else
+ {
+ self->in_s->end += read_bytes;
+ }
+ }
+
+ read_so_far = (int)(self->in_s->end - self->in_s->data);
+
+ if (read_so_far == self->header_size)
+ {
+ if (self->trans_data_in != 0)
+ {
+ rv = self->trans_data_in(self);
+ init_stream(self->in_s, 0);
+ }
+ }
}
- }
}
- }
- else /* connected server or client (2 or 3) */
- {
- if (g_tcp_can_recv(self->sck, 0))
+
+ return rv;
+}
+
+/*****************************************************************************/
+int APP_CC
+trans_force_read_s(struct trans *self, struct stream *in_s, int size)
+{
+ int rcvd;
+
+ if (self->status != TRANS_STATUS_UP)
+ {
+ return 1;
+ }
+
+ while (size > 0)
{
- read_so_far = (int)(self->in_s->end - self->in_s->data);
- to_read = self->header_size - read_so_far;
- if (to_read > 0)
- {
- read_bytes = g_tcp_recv(self->sck, self->in_s->end, to_read, 0);
- if (read_bytes == -1)
+ rcvd = g_tcp_recv(self->sck, in_s->end, size, 0);
+
+ if (rcvd == -1)
+ {
+ if (g_tcp_last_error_would_block(self->sck))
+ {
+ if (!g_tcp_can_recv(self->sck, 10))
+ {
+ /* check for term here */
+ }
+ }
+ else
+ {
+ /* error */
+ self->status = TRANS_STATUS_DOWN;
+ return 1;
+ }
+ }
+ else if (rcvd == 0)
{
- if (g_tcp_last_error_would_block(self->sck))
- {
- /* ok, but shouldn't happen */
- }
- else
- {
/* error */
self->status = TRANS_STATUS_DOWN;
return 1;
- }
- }
- else if (read_bytes == 0)
- {
- /* error */
- self->status = TRANS_STATUS_DOWN;
- return 1;
}
else
{
- self->in_s->end += read_bytes;
+ in_s->end += rcvd;
+ size -= rcvd;
}
- }
- read_so_far = (int)(self->in_s->end - self->in_s->data);
- if (read_so_far == self->header_size)
- {
- if (self->trans_data_in != 0)
- {
- rv = self->trans_data_in(self);
- init_stream(self->in_s, 0);
- }
- }
}
- }
- return rv;
+
+ return 0;
}
/*****************************************************************************/
int APP_CC
-trans_force_read_s(struct trans* self, struct stream* in_s, int size)
+trans_force_read(struct trans *self, int size)
{
- int rcvd;
+ return trans_force_read_s(self, self->in_s, size);
+}
- if (self->status != TRANS_STATUS_UP)
- {
- return 1;
- }
- while (size > 0)
- {
- rcvd = g_tcp_recv(self->sck, in_s->end, size, 0);
- if (rcvd == -1)
+/*****************************************************************************/
+int APP_CC
+trans_force_write_s(struct trans *self, struct stream *out_s)
+{
+ int size;
+ int total;
+ int sent;
+
+ if (self->status != TRANS_STATUS_UP)
{
- if (g_tcp_last_error_would_block(self->sck))
- {
- if (!g_tcp_can_recv(self->sck, 10))
- {
- /* check for term here */
- }
- }
- else
- {
- /* error */
- self->status = TRANS_STATUS_DOWN;
return 1;
- }
- }
- else if (rcvd == 0)
- {
- /* error */
- self->status = TRANS_STATUS_DOWN;
- return 1;
}
- else
+
+ size = (int)(out_s->end - out_s->data);
+ total = 0;
+
+ while (total < size)
{
- in_s->end += rcvd;
- size -= rcvd;
+ sent = g_tcp_send(self->sck, out_s->data + total, size - total, 0);
+
+ if (sent == -1)
+ {
+ if (g_tcp_last_error_would_block(self->sck))
+ {
+ if (!g_tcp_can_send(self->sck, 10))
+ {
+ /* check for term here */
+ }
+ }
+ else
+ {
+ /* error */
+ self->status = TRANS_STATUS_DOWN;
+ return 1;
+ }
+ }
+ else if (sent == 0)
+ {
+ /* error */
+ self->status = TRANS_STATUS_DOWN;
+ return 1;
+ }
+ else
+ {
+ total = total + sent;
+ }
}
- }
- return 0;
+
+ return 0;
}
/*****************************************************************************/
int APP_CC
-trans_force_read(struct trans* self, int size)
+trans_force_write(struct trans *self)
{
- return trans_force_read_s(self, self->in_s, size);
+ return trans_force_write_s(self, self->out_s);
}
/*****************************************************************************/
int APP_CC
-trans_force_write_s(struct trans* self, struct stream* out_s)
+trans_connect(struct trans *self, const char *server, const char *port,
+ int timeout)
{
- int size;
- int total;
- int sent;
+ int error;
- if (self->status != TRANS_STATUS_UP)
- {
- return 1;
- }
- size = (int)(out_s->end - out_s->data);
- total = 0;
- while (total < size)
- {
- sent = g_tcp_send(self->sck, out_s->data + total, size - total, 0);
- if (sent == -1)
+ if (self->sck != 0)
{
- if (g_tcp_last_error_would_block(self->sck))
- {
- if (!g_tcp_can_send(self->sck, 10))
- {
- /* check for term here */
- }
- }
- else
- {
- /* error */
- self->status = TRANS_STATUS_DOWN;
- return 1;
- }
+ g_tcp_close(self->sck);
}
- else if (sent == 0)
+
+ if (self->mode == TRANS_MODE_TCP) /* tcp */
{
- /* error */
- self->status = TRANS_STATUS_DOWN;
- return 1;
+ self->sck = g_tcp_socket();
+ g_tcp_set_non_blocking(self->sck);
+ error = g_tcp_connect(self->sck, server, port);
+ }
+ else if (self->mode == TRANS_MODE_UNIX) /* unix socket */
+ {
+ self->sck = g_tcp_local_socket();
+ g_tcp_set_non_blocking(self->sck);
+ error = g_tcp_local_connect(self->sck, port);
}
else
{
- total = total + sent;
+ self->status = TRANS_STATUS_DOWN;
+ return 1;
}
- }
- return 0;
-}
-/*****************************************************************************/
-int APP_CC
-trans_force_write(struct trans* self)
-{
- return trans_force_write_s(self, self->out_s);
+ if (error == -1)
+ {
+ if (g_tcp_last_error_would_block(self->sck))
+ {
+ if (g_tcp_can_send(self->sck, timeout))
+ {
+ self->status = TRANS_STATUS_UP; /* ok */
+ self->type1 = TRANS_TYPE_CLIENT; /* client */
+ return 0;
+ }
+ }
+
+ return 1;
+ }
+
+ self->status = TRANS_STATUS_UP; /* ok */
+ self->type1 = TRANS_TYPE_CLIENT; /* client */
+ return 0;
}
/*****************************************************************************/
int APP_CC
-trans_connect(struct trans* self, const char* server, const char* port,
- int timeout)
+trans_listen_address(struct trans *self, char *port, const char *address)
{
- int error;
-
- if (self->sck != 0)
- {
- g_tcp_close(self->sck);
- }
- if (self->mode == TRANS_MODE_TCP) /* tcp */
- {
- self->sck = g_tcp_socket();
- g_tcp_set_non_blocking(self->sck);
- error = g_tcp_connect(self->sck, server, port);
- }
- else if (self->mode == TRANS_MODE_UNIX) /* unix socket */
- {
- self->sck = g_tcp_local_socket();
- g_tcp_set_non_blocking(self->sck);
- error = g_tcp_local_connect(self->sck, port);
- }
- else
- {
- self->status = TRANS_STATUS_DOWN;
- return 1;
- }
- if (error == -1)
- {
- if (g_tcp_last_error_would_block(self->sck))
+ if (self->sck != 0)
{
- if (g_tcp_can_send(self->sck, timeout))
- {
- self->status = TRANS_STATUS_UP; /* ok */
- self->type1 = TRANS_TYPE_CLIENT; /* client */
- return 0;
- }
+ g_tcp_close(self->sck);
}
- return 1;
- }
- self->status = TRANS_STATUS_UP; /* ok */
- self->type1 = TRANS_TYPE_CLIENT; /* client */
- return 0;
-}
-/*****************************************************************************/
-int APP_CC
-trans_listen_address(struct trans* self, char* port, const char* address)
-{
- if (self->sck != 0)
- {
- g_tcp_close(self->sck);
- }
- if (self->mode == TRANS_MODE_TCP) /* tcp */
- {
- self->sck = g_tcp_socket();
- g_tcp_set_non_blocking(self->sck);
- if (g_tcp_bind_address(self->sck, port, address) == 0)
+ if (self->mode == TRANS_MODE_TCP) /* tcp */
{
- if (g_tcp_listen(self->sck) == 0)
- {
- self->status = TRANS_STATUS_UP; /* ok */
- self->type1 = TRANS_TYPE_LISTENER; /* listener */
- return 0;
- }
+ self->sck = g_tcp_socket();
+ g_tcp_set_non_blocking(self->sck);
+
+ if (g_tcp_bind_address(self->sck, port, address) == 0)
+ {
+ if (g_tcp_listen(self->sck) == 0)
+ {
+ self->status = TRANS_STATUS_UP; /* ok */
+ self->type1 = TRANS_TYPE_LISTENER; /* listener */
+ return 0;
+ }
+ }
}
- }
- else if (self->mode == TRANS_MODE_UNIX) /* unix socket */
- {
- g_free(self->listen_filename);
- self->listen_filename = 0;
- g_file_delete(port);
- self->sck = g_tcp_local_socket();
- g_tcp_set_non_blocking(self->sck);
- if (g_tcp_local_bind(self->sck, port) == 0)
+ else if (self->mode == TRANS_MODE_UNIX) /* unix socket */
{
- self->listen_filename = g_strdup(port);
- if (g_tcp_listen(self->sck) == 0)
- {
- g_chmod_hex(port, 0xffff);
- self->status = TRANS_STATUS_UP; /* ok */
- self->type1 = TRANS_TYPE_LISTENER; /* listener */
- return 0;
- }
+ g_free(self->listen_filename);
+ self->listen_filename = 0;
+ g_file_delete(port);
+ self->sck = g_tcp_local_socket();
+ g_tcp_set_non_blocking(self->sck);
+
+ if (g_tcp_local_bind(self->sck, port) == 0)
+ {
+ self->listen_filename = g_strdup(port);
+
+ if (g_tcp_listen(self->sck) == 0)
+ {
+ g_chmod_hex(port, 0xffff);
+ self->status = TRANS_STATUS_UP; /* ok */
+ self->type1 = TRANS_TYPE_LISTENER; /* listener */
+ return 0;
+ }
+ }
}
- }
- return 1;
+
+ return 1;
}
/*****************************************************************************/
int APP_CC
-trans_listen(struct trans* self, char* port)
+trans_listen(struct trans *self, char *port)
{
- return trans_listen_address(self, port, "0.0.0.0");
+ return trans_listen_address(self, port, "0.0.0.0");
}
/*****************************************************************************/
-struct stream* APP_CC
-trans_get_in_s(struct trans* self)
+struct stream *APP_CC
+trans_get_in_s(struct trans *self)
{
- struct stream * rv = (struct stream *)NULL;
- if (self == NULL) {
- rv = (struct stream *)NULL;
- }
- else {
- rv = self->in_s;
- }
- return rv;
+ struct stream *rv = (struct stream *)NULL;
+
+ if (self == NULL)
+ {
+ rv = (struct stream *)NULL;
+ }
+ else
+ {
+ rv = self->in_s;
+ }
+
+ return rv;
}
/*****************************************************************************/
-struct stream* APP_CC
-trans_get_out_s(struct trans* self, int size)
+struct stream *APP_CC
+trans_get_out_s(struct trans *self, int size)
{
- struct stream * rv = (struct stream *)NULL;
- if (self == NULL) {
- rv = (struct stream *)NULL;
- }
- else {
- init_stream(self->out_s, size);
- rv = self->out_s;
- }
- return rv;
+ struct stream *rv = (struct stream *)NULL;
+
+ if (self == NULL)
+ {
+ rv = (struct stream *)NULL;
+ }
+ else
+ {
+ init_stream(self->out_s, size);
+ rv = self->out_s;
+ }
+
+ return rv;
}