summaryrefslogtreecommitdiffstats
path: root/tinyNET/src/tnet_proxy_plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'tinyNET/src/tnet_proxy_plugin.c')
-rw-r--r--tinyNET/src/tnet_proxy_plugin.c284
1 files changed, 284 insertions, 0 deletions
diff --git a/tinyNET/src/tnet_proxy_plugin.c b/tinyNET/src/tnet_proxy_plugin.c
new file mode 100644
index 0000000..dbcd143
--- /dev/null
+++ b/tinyNET/src/tnet_proxy_plugin.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2010-2015 Mamadou DIOP.
+ * Copyright (C) 2015 Doubango Telecom.
+ *
+ * This file is part of Open Source Doubango Framework.
+ *
+ * DOUBANGO is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DOUBANGO is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DOUBANGO.
+ *
+ */
+#include "tnet_proxy_plugin.h"
+
+#include "tsk_memory.h"
+#include "tsk_string.h"
+#include "tsk_debug.h"
+
+#if !defined(TNET_PROXY_NODE_MAX_PLUGINS)
+# define TNET_PROXY_NODE_MAX_PLUGINS 10
+#endif
+
+const tnet_proxy_node_plugin_def_t* __tnet_proxy_node_plugins[TNET_PROXY_NODE_MAX_PLUGINS] = {0};
+
+
+tsk_bool_t tnet_proxy_node_is_nettransport_supported(enum tnet_proxy_type_e proxy_type, enum tnet_socket_type_e socket_type)
+{
+ switch (proxy_type) {
+ case tnet_proxy_type_http:
+ case tnet_proxy_type_https:
+ return TNET_SOCKET_TYPE_IS_STREAM(socket_type);
+
+ case tnet_proxy_type_socks4:
+ case tnet_proxy_type_socks4a:
+ return TNET_SOCKET_TYPE_IS_STREAM(socket_type) && TNET_SOCKET_TYPE_IS_IPV4(socket_type);
+ case tnet_proxy_type_socks5: // SOCKS5 adds support for UDP and IPv6
+ return TNET_SOCKET_TYPE_IS_STREAM(socket_type) || TNET_SOCKET_TYPE_IS_DGRAM(socket_type);// for now we don't support socks for UDP (just like a browser)
+ default:
+ return tsk_false;
+ }
+}
+
+int tnet_proxy_node_init(tnet_proxy_node_t* self)
+{
+ if (self) {
+ self->socket.fd = TNET_INVALID_FD;
+ self->socket.type = tnet_socket_type_invalid;
+ }
+ return 0;
+}
+
+int tnet_proxy_node_configure(tnet_proxy_node_t* self, ...)
+{
+ va_list ap;
+ int ret = 0;
+
+ if (!self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ va_start(ap, self);
+ ret = tnet_proxy_node_configure_2(self, &ap);
+ va_end(ap);
+ return ret;
+}
+
+int tnet_proxy_node_configure_2(tnet_proxy_node_t* self, va_list* app)
+{
+ int ret = 0;
+ tnet_proxy_node_param_type_t ptype;
+
+ if (!self || !app) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ while ((ptype = va_arg(*app, tnet_proxy_node_param_type_t)) != tnet_proxy_node_param_type_null) {
+ switch (ptype) {
+ case tnet_proxy_node_param_type_destination_address:
+ case tnet_proxy_node_param_type_proxy_address: {
+ // (const char*)(HOST_STR), (int)(PORT_INT)
+ const char* HOST_STR = va_arg(*app, const char*);
+ int PORT_INT = va_arg(*app, int);
+ if (PORT_INT < 1 || PORT_INT > 0xFFF) {
+ TSK_DEBUG_ERROR("Invalid value for port number: %d", PORT_INT);
+ ret = -3;
+ goto bail;
+ }
+ if (ptype == tnet_proxy_node_param_type_destination_address) {
+ tsk_strupdate(&self->dst_host, HOST_STR);
+ self->dst_port = (tnet_port_t)PORT_INT;
+ }
+ else {
+ tsk_strupdate(&self->proxy_host, HOST_STR);
+ self->proxy_port = (tnet_port_t)PORT_INT;
+ }
+ break;
+ }
+ case tnet_proxy_node_param_type_ipv6: {
+ /* (tsk_bool_t)(IPV6_BOOL) */
+ self->ipv6 = va_arg(*app, tsk_bool_t);
+ break;
+ }
+ case tnet_proxy_node_param_type_credentials: {
+ /* (const char*)(LOGIN_STR), (const char*)(PASSWORD_STR) */
+ const char* LOGIN_STR = va_arg(*app, const char*);
+ const char* PASSWORD_STR = va_arg(*app, const char*);
+ tsk_strupdate(&self->login, LOGIN_STR);
+ tsk_strupdate(&self->password, PASSWORD_STR);
+ break;
+ }
+ case tnet_proxy_node_param_type_socket: {
+ /* (tnet_fd_t)(FD_FD), (enum tnet_socket_type_e)(type) */
+ self->socket.fd = va_arg(*app, tnet_fd_t);
+ self->socket.type = va_arg(*app, enum tnet_socket_type_e);
+ break;
+ }
+#if TNET_UNDER_APPLE
+ case tnet_proxy_node_param_type_cfstreams: {
+ /* (CFReadStreamRef)(READ_CFSTREAM), (CFWriteStreamRef)(WRITE_CFSTREAM) */
+ CFReadStreamRef READ_CFSTREAM = va_arg(*app, CFReadStreamRef);
+ CFWriteStreamRef WRITE_CFSTREAM = va_arg(*app, CFWriteStreamRef);
+ if (self->cf_read_stream) CFRelease(self->cf_read_stream), self->cf_read_stream = tsk_null;
+ if (self->cf_write_stream) CFRelease(self->cf_write_stream), self->cf_write_stream = tsk_null;
+ if (READ_CFSTREAM) self->cf_read_stream = (CFReadStreamRef)CFRetain(READ_CFSTREAM);
+ if (WRITE_CFSTREAM) self->cf_write_stream = (CFWriteStreamRef)CFRetain(WRITE_CFSTREAM);
+ break;
+ }
+#endif /* TNET_UNDER_APPLE */
+ default: {
+ TSK_DEBUG_ERROR("%d not valid param type", ptype);
+ ret = -2;
+ goto bail;
+ }
+ }
+ }
+
+bail:
+ return ret;
+}
+
+int tnet_proxy_node_start_handshaking(tnet_proxy_node_t* self)
+{
+ if (!self || !self->plugin || !self->plugin->start_handshaking) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return self->plugin->start_handshaking(self);
+}
+
+int tnet_proxy_node_set_handshaking_data(tnet_proxy_node_t* self, const void* data_ptr, tsk_size_t data_size)
+{
+ if (!self || !data_ptr || !data_size || !self->plugin || !self->plugin->set_handshaking_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return self->plugin->set_handshaking_data(self, data_ptr, data_size);
+}
+
+int tnet_proxy_node_get_handshaking_pending_data(tnet_proxy_node_t* self, void** data_pptr, tsk_size_t* data_psize)
+{
+ if (!self || !data_pptr || !data_psize || !self->plugin || !self->plugin->get_handshaking_pending_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return self->plugin->get_handshaking_pending_data(self, data_pptr, data_psize);
+}
+
+int tnet_proxy_node_get_handshaking_completed(tnet_proxy_node_t* self, tsk_bool_t* completed)
+{
+ if (!self || !completed || !self->plugin || !self->plugin->get_handshaking_completed) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return self->plugin->get_handshaking_completed(self, completed);
+}
+
+int tnet_proxy_node_deinit(tnet_proxy_node_t* self)
+{
+ if (self) {
+ TSK_FREE(self->dst_host);
+ TSK_FREE(self->proxy_host);
+ TSK_FREE(self->login);
+ TSK_FREE(self->password);
+#if TNET_UNDER_APPLE
+ if (self->cf_read_stream) {
+ CFRelease(self->cf_read_stream), self->cf_read_stream = tsk_null;
+ }
+ if (self->cf_write_stream) {
+ CFRelease(self->cf_write_stream), self->cf_write_stream = tsk_null;
+ }
+#endif
+ }
+ return 0;
+}
+
+int tnet_proxy_node_plugin_register(const tnet_proxy_node_plugin_def_t* plugin)
+{
+ tsk_size_t i;
+ if (!plugin || tsk_strnullORempty(plugin->desc)) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ /* add or replace the plugin */
+ for (i = 0; i<TNET_PROXY_NODE_MAX_PLUGINS; i++) {
+ if (!__tnet_proxy_node_plugins[i] || (__tnet_proxy_node_plugins[i] == plugin)){
+ __tnet_proxy_node_plugins[i] = plugin;
+ TSK_DEBUG_INFO("Register network proxy node plugin: %s", plugin->desc);
+ return 0;
+ }
+ }
+
+ TSK_DEBUG_ERROR("There are already %d network proxy node plugins.", TNET_PROXY_NODE_MAX_PLUGINS);
+ return -2;
+}
+
+int tnet_proxy_node_plugin_unregister(const tnet_proxy_node_plugin_def_t* plugin)
+{
+ tsk_size_t i;
+ tsk_bool_t found = tsk_false;
+ if (!plugin) {
+ TSK_DEBUG_ERROR("Invalid Parameter");
+ return -1;
+ }
+
+ /* find the plugin to unregister */
+ for (i = 0; i<TNET_PROXY_NODE_MAX_PLUGINS && __tnet_proxy_node_plugins[i]; i++) {
+ if (__tnet_proxy_node_plugins[i] == plugin) {
+ TSK_DEBUG_INFO("UnRegister network proxy node plugin: %s", plugin->desc);
+ __tnet_proxy_node_plugins[i] = tsk_null;
+ found = tsk_true;
+ break;
+ }
+ }
+
+ /* compact */
+ if (found) {
+ for (; i<(TNET_PROXY_NODE_MAX_PLUGINS - 1); i++) {
+ if (__tnet_proxy_node_plugins[i+1]) {
+ __tnet_proxy_node_plugins[i] = __tnet_proxy_node_plugins[i+1];
+ }
+ else {
+ break;
+ }
+ }
+ __tnet_proxy_node_plugins[i] = tsk_null;
+ }
+ return (found ? 0 : -2);
+}
+
+tsk_size_t tnet_proxy_node_plugin_registry_count()
+{
+ tsk_size_t count;
+ for(count = 0;
+ count < TNET_PROXY_NODE_MAX_PLUGINS && __tnet_proxy_node_plugins[count];
+ ++count) ;
+ return count;
+}
+
+tnet_proxy_node_t* tnet_proxy_node_create(enum tnet_proxy_type_e type)
+{
+ tsk_size_t i;
+ tnet_proxy_node_t* node = tsk_null;
+ for (i = 0; i<TNET_PROXY_NODE_MAX_PLUGINS && __tnet_proxy_node_plugins[i]; i++) {
+ if ((__tnet_proxy_node_plugins[i]->type & type) == type) {
+ if ((node = tsk_object_new(__tnet_proxy_node_plugins[i]->objdef))) {
+ node->type = type;
+ node->plugin = __tnet_proxy_node_plugins[i];
+ break;
+ }
+ }
+ }
+ return node;
+} \ No newline at end of file
OpenPOWER on IntegriCloud