X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Fsilcstress%2Fsilcstress.c;fp=apps%2Fsilcstress%2Fsilcstress.c;h=0000000000000000000000000000000000000000;hb=72c2de619079457f7a68100eb13385275a424a23;hp=874c5b1b3f17f07a0d0b4247651654e3e9556bb4;hpb=e7b6c157b80152bf9fb9266e6bdd93f9fb0db776;p=runtime.git diff --git a/apps/silcstress/silcstress.c b/apps/silcstress/silcstress.c deleted file mode 100644 index 874c5b1b..00000000 --- a/apps/silcstress/silcstress.c +++ /dev/null @@ -1,631 +0,0 @@ -/* - - silcstress.c - - Author: Pekka Riikonen - - Copyright (C) 2005 Pekka Riikonen - - This program 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; version 2 of the License. - - This program 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. - -*/ - -/* - TODO: - - - join to created clients with another client, to get the sent messages - as reply (channel message). - - create x clients - -*/ - -/* - Results: - - SILC Server 0.9.20 (release), Linux 2.6.11, RAM 512 MB: - - - 3000 channels == silcd size 6 MB (-c 3000 -n) - - 10000 channels == silcd size 17 MB (-c 10000 -n) - - 30000 channels == silcd size 48 MB (-c 30000 -n) - (creating 30000 channels take 14 minutes, because JOIN is LAG_STRICT - command, which prevents one client flooding server with commands + - Qos was enabled too) - - - SILC Server 0.9.20 (debug, stack-trace), Linux 2.6.11, RAM 512 MB: - - - 3000 channels == silcd size 10 MB (-c 3000 -n) - - 10000 channels == silcd size 37 MB (-c 10000 -n) - - - 1 channel, default data flood, QoS == silcd load < 1.0% - - 10 channels, default data flood, QoS == silcd load < 4.0% - - 100 channels, default data flood, QoS == silcd load < 5.0% - (Qos: rate=20, bytes_limit=500B, usec_limit=200000) - -*/ - -#include "silcincludes.h" -#include "silcclient.h" - -typedef struct { - SilcClient client; - SilcClientConnection conn; - int msize; - int loops; - int flood; - int channels; - int threads; - bool nosend; - SilcMutex m; -} *SilcStress; - -typedef struct { - SilcStress sc; - SilcDList channels; -} *SilcStressWorker; - -SilcClientOperations ops; - -/* Long command line options */ -static struct option long_opts[] = -{ - { "server", 1, NULL,'s' }, - { "port", 1, NULL,'p' }, - { "channels", 1, NULL,'c' }, - { "msize", 1, NULL,'m' }, - { "loops", 1, NULL,'l' }, - { "flood", 1, NULL,'f' }, - { "nosend", 0, NULL,'n' }, - { "threads", 1, NULL,'t' }, - { "debug", 2, NULL, 'd' }, - { "help", 0, NULL, 'h' }, - { "version", 0, NULL,'V' }, - - { NULL, 0, NULL, 0 } -}; - -static void silc_stress_usage(void) -{ - printf("" -"Usage: silcstress [options]\n" -"\n" -" Generic Options:\n" -" -s --server=server Server to connect\n" -" -p --port=NUMBER Server port to connect (def: 706)\n" -" -c --channels=NUMBER Number of channels to create (def: 1)\n" -" -m --msize=NUMBER Size of message in bytes (def: 512)\n" -" -l --loops=NUMBER Number of loops to send data (def: 1024)\n" -" -f --flood=NUMBER Send message in every usec (def: 50000)\n" -" -n --nosend Don't send any data\n" -" -t --threads=NUMBER Number of threads to use (def: 1)\n" -" -d --debug=string Enable debugging\n" -" -h --help Display this message and exit\n" -" -V --version Display version and exit\n" -"\n"); - exit(0); -} - -int main(int argc, char **argv) -{ - int opt, option_index; - int c = 1, port = 706, b = 512, l = 1024, f = 50000, n = FALSE, t = 1; - char *server = NULL; - SilcStress sc; - - if (argc > 1) { - while ((opt = getopt_long(argc, argv, "d:hVc:s:p:m:l:f:nt:", - long_opts, &option_index)) != EOF) { - switch(opt) { - case 'h': - silc_stress_usage(); - break; - case 'V': - printf("SILC Stress, version %s\n", silc_dist_version); - printf("(c) 2005 Pekka Riikonen \n"); - exit(0); - break; - case 'd': -#ifdef SILC_DEBUG - silc_log_debug(TRUE); - silc_log_debug_hexdump(TRUE); - silc_log_quick(TRUE); - if (optarg) - silc_log_set_debug_string(optarg); -#else - fprintf(stderr, - "Run-time debugging is not enabled. To enable it recompile\n" - "the server with --enable-debug configuration option.\n"); -#endif - break; - case 'c': - c = atoi(optarg); - break; - case 'l': - l = atoi(optarg); - break; - case 'f': - f = atoi(optarg); - break; - case 'm': - b = atoi(optarg); - break; - case 't': - t = atoi(optarg); - break; - case 'p': - port = atoi(optarg); - break; - case 's': - server = strdup(optarg); - break; - case 'n': - n = TRUE; - break; - default: - silc_stress_usage(); - break; - } - } - } - - if (!server) - silc_stress_usage(); - - sc = silc_calloc(1, sizeof(*sc)); - if (!sc) - return 1; - sc->channels = c; - sc->msize = b; - sc->loops = l; - sc->flood = f; - sc->nosend = n; - sc->threads = t; - - sc->client = silc_client_alloc(&ops, NULL, sc, NULL); - if (!sc->client) - return 1; - - sc->client->username = silc_get_username(); - sc->client->hostname = silc_net_localhost(); - sc->client->realname = strdup("SILC STRESS"); - - if (!silc_client_init(sc->client)) - return 1; - - if (!silc_load_key_pair("silcstress.pub", "silcstress.prv", "", - &sc->client->pkcs, - &sc->client->public_key, - &sc->client->private_key)) { - if (!silc_create_key_pair("rsa", 2048, "silcstress.pub", - "silcstress.prv", NULL, "", - &sc->client->pkcs, - &sc->client->public_key, - &sc->client->private_key, FALSE)) { - return 1; - } - } - - silc_mutex_alloc(&sc->m); - - silc_client_connect_to_server(sc->client, NULL, port, server, sc); - - silc_client_run(sc->client); - - silc_mutex_free(sc->m); - silc_client_free(sc->client); - silc_free(sc); - silc_free(server); - - return 0; -} - -/* Worker thread */ - -static void * -silc_stress_worker(void *context) -{ - SilcStressWorker w = context; - SilcClient client = w->sc->client; - SilcClientConnection conn = w->sc->conn; - SilcChannelEntry channel; - char *tmp; - int i; - - tmp = silc_calloc(w->sc->msize, sizeof(*tmp)); - if (!tmp) { - fprintf(stderr, "out of mem\n"); - silc_dlist_uninit(w->channels); - return NULL; - } - - memset(tmp, 'M', w->sc->msize); - - for (i = 0; i < w->sc->loops; i++) { - silc_dlist_start(w->channels); - while ((channel = silc_dlist_get(w->channels)) != SILC_LIST_END) { - /* Our packet routines don't like threads, so let's lock :( */ - silc_mutex_lock(w->sc->m); - if (!w->sc->conn) { - silc_dlist_uninit(w->channels); - return NULL; - } - silc_client_send_channel_message(client, conn, channel, NULL, 0, - tmp, w->sc->msize, TRUE); - silc_mutex_unlock(w->sc->m); - } - usleep(w->sc->flood); - } - - silc_dlist_uninit(w->channels); - silc_free(tmp); - - return NULL; -} - - -/* "say" client operation is a message from the client library to the - application. It may include error messages or something else. We - just dump them to screen. */ - -static void -silc_say(SilcClient client, SilcClientConnection conn, - SilcClientMessageType type, char *msg, ...) -{ - char str[200]; - va_list va; - va_start(va, msg); - vsnprintf(str, sizeof(str) - 1, msg, va); - fprintf(stdout, "%s\n", str); - va_end(va); -} - - -/* Message for a channel. The `sender' is the sender of the message - The `channel' is the channel. The `message' is the message. Note - that `message' maybe NULL. The `flags' indicates message flags - and it is used to determine how the message can be interpreted - (like it may tell the message is multimedia message). */ - -static void -silc_channel_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcChannelEntry channel, - SilcMessagePayload payload, - SilcChannelPrivateKey key, - SilcMessageFlags flags, const unsigned char *message, - SilcUInt32 message_len) -{ - -} - - -/* Private message to the client. The `sender' is the sender of the - message. The message is `message'and maybe NULL. The `flags' - indicates message flags and it is used to determine how the message - can be interpreted (like it may tell the message is multimedia - message). */ - -static void -silc_private_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcMessagePayload payload, - SilcMessageFlags flags, - const unsigned char *message, - SilcUInt32 message_len) -{ -} - - -/* Notify message to the client. The notify arguments are sent in the - same order as servers sends them. The arguments are same as received - from the server except for ID's. If ID is received application receives - the corresponding entry to the ID. For example, if Client ID is received - application receives SilcClientEntry. Also, if the notify type is - for channel the channel entry is sent to application (even if server - does not send it because client library gets the channel entry from - the Channel ID in the packet's header). */ - -static void -silc_notify(SilcClient client, SilcClientConnection conn, - SilcNotifyType type, ...) -{ - -} - - -/* Command handler. This function is called always in the command function. - If error occurs it will be called as well. `conn' is the associated - client connection. `cmd_context' is the command context that was - originally sent to the command. `success' is FALSE if error occurred - during command. `command' is the command being processed. It must be - noted that this is not reply from server. This is merely called just - after application has called the command. Just to tell application - that the command really was processed. */ - -static void -silc_command(SilcClient client, SilcClientConnection conn, - SilcClientCommandContext cmd_context, bool success, - SilcCommand command, SilcStatus status) -{ - /* If error occurred in client library with our command, print the error */ - if (status != SILC_STATUS_OK) - fprintf(stderr, "COMMAND %s: %s\n", - silc_get_command_name(command), - silc_get_status_message(status)); -} - - -/* Command reply handler. This function is called always in the command reply - function. If error occurs it will be called as well. Normal scenario - is that it will be called after the received command data has been parsed - and processed. The function is used to pass the received command data to - the application. - - `conn' is the associated client connection. `cmd_payload' is the command - payload data received from server and it can be ignored. It is provided - if the application would like to re-parse the received command data, - however, it must be noted that the data is parsed already by the library - thus the payload can be ignored. `success' is FALSE if error occurred. - In this case arguments are not sent to the application. The `status' is - the command reply status server returned. The `command' is the command - reply being processed. The function has variable argument list and each - command defines the number and type of arguments it passes to the - application (on error they are not sent). */ - -static void -silc_command_reply(SilcClient client, SilcClientConnection conn, - SilcCommandPayload cmd_payload, bool success, - SilcCommand command, SilcStatus status, ...) -{ - SilcStress sc = client->application; - va_list va; - - /* If error occurred in client library with our command, print the error */ - if (status != SILC_STATUS_OK) - fprintf(stderr, "COMMAND REPLY %s: %s\n", - silc_get_command_name(command), - silc_get_status_message(status)); - - va_start(va, status); - - /* Check for successful JOIN */ - if (command == SILC_COMMAND_JOIN && sc->nosend == FALSE && - silc_hash_table_count(conn->local_entry->channels) == sc->channels) { - /* Create worker threads for data sending */ - SilcStressWorker w; - SilcHashTableList htl; - SilcChannelUser chu; - int i, k; - - printf("Creating %d threads (%d channels/thread)\n", - sc->threads, silc_hash_table_count(conn->local_entry->channels) / - sc->threads); - - silc_hash_table_list(conn->local_entry->channels, &htl); - for (i = 0; i < sc->threads; i++) { - - w = silc_calloc(1, sizeof(*w)); - if (!w) { - fprintf(stderr, "out of mem\n"); - exit(1); - } - - w->sc = sc; - w->channels = silc_dlist_init(); - if (!w->channels) { - fprintf(stderr, "out of mem\n"); - exit(1); - } - - for (k = 0; k < (silc_hash_table_count(conn->local_entry->channels) / - sc->threads); k++) - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) - silc_dlist_add(w->channels, chu->channel); - - silc_thread_create(silc_stress_worker, w, FALSE); - } - silc_hash_table_list_reset(&htl); - } - - va_end(va); -} - - -/* Called to indicate that connection was either successfully established - or connecting failed. This is also the first time application receives - the SilcClientConnection objecet which it should save somewhere. - If the `success' is FALSE the application must always call the function - silc_client_close_connection. */ - -static void -silc_connected(SilcClient client, SilcClientConnection conn, - SilcClientConnectionStatus status) -{ - SilcStress sc = client->application; - char tmp[16]; - int i; - - if (status != SILC_CLIENT_CONN_SUCCESS) { - fprintf(stderr, "Could not connect to server\n"); - silc_client_close_connection(client, conn); - return; - } - - fprintf(stdout, "Connected to server.\n"); - - /* Save the connection context */ - sc->conn = conn; - - /* Join channels */ - for (i = 0; i < sc->channels; i++) { - memset(tmp, 0, sizeof(tmp)); - snprintf(tmp, sizeof(tmp) - 1, "JOIN %d", i); - - /* Our packet routines don't like threads, so let's lock :( */ - silc_mutex_lock(sc->m); - silc_client_command_call(client, conn, tmp); - silc_mutex_unlock(sc->m); - usleep(50000); - } -} - - -/* Called to indicate that connection was disconnected to the server. - The `status' may tell the reason of the disconnection, and if the - `message' is non-NULL it may include the disconnection message - received from server. */ - -static void -silc_disconnected(SilcClient client, SilcClientConnection conn, - SilcStatus status, const char *message) -{ - SilcStress sc = client->application; - - /* We got disconnected from server */ - sc->conn = NULL; - fprintf(stdout, "%s:%s\n", silc_get_status_message(status), - message); -} - - -/* Find authentication method and authentication data by hostname and - port. The hostname may be IP address as well. When the authentication - method has been resolved the `completion' callback with the found - authentication method and authentication data is called. The `conn' - may be NULL. */ - -static void -silc_get_auth_method(SilcClient client, SilcClientConnection conn, - char *hostname, SilcUInt16 port, - SilcGetAuthMeth completion, - void *context) -{ - completion(TRUE, SILC_AUTH_NONE, NULL, 0, context); -} - - -/* Verifies received public key. The `conn_type' indicates which entity - (server, client etc.) has sent the public key. If user decides to trust - the application may save the key as trusted public key for later - use. The `completion' must be called after the public key has been - verified. */ - -static void -silc_verify_public_key(SilcClient client, SilcClientConnection conn, - SilcSocketType conn_type, unsigned char *pk, - SilcUInt32 pk_len, SilcSKEPKType pk_type, - SilcVerifyPublicKey completion, void *context) -{ - completion(TRUE, context); -} - - -/* Ask (interact, that is) a passphrase from user. The passphrase is - returned to the library by calling the `completion' callback with - the `context'. The returned passphrase SHOULD be in UTF-8 encoded, - if not then the library will attempt to encode. */ - -static void -silc_ask_passphrase(SilcClient client, SilcClientConnection conn, - SilcAskPassphrase completion, void *context) -{ - completion(NULL, 0, context); -} - - -/* Notifies application that failure packet was received. This is called - if there is some protocol active in the client. The `protocol' is the - protocol context. The `failure' is opaque pointer to the failure - indication. Note, that the `failure' is protocol dependant and - application must explicitly cast it to correct type. Usually `failure' - is 32 bit failure type (see protocol specs for all protocol failure - types). */ - -static void -silc_failure(SilcClient client, SilcClientConnection conn, - SilcProtocol protocol, void *failure) -{ - fprintf(stderr, "Connecting failed (protocol failure)\n"); -} - - -/* Asks whether the user would like to perform the key agreement protocol. - This is called after we have received an key agreement packet or an - reply to our key agreement packet. This returns TRUE if the user wants - the library to perform the key agreement protocol and FALSE if it is not - desired (application may start it later by calling the function - silc_client_perform_key_agreement). If TRUE is returned also the - `completion' and `context' arguments must be set by the application. */ - -static bool -silc_key_agreement(SilcClient client, SilcClientConnection conn, - SilcClientEntry client_entry, const char *hostname, - SilcUInt16 port, SilcKeyAgreementCallback *completion, - void **context) -{ - return FALSE; -} - - -/* Notifies application that file transfer protocol session is being - requested by the remote client indicated by the `client_entry' from - the `hostname' and `port'. The `session_id' is the file transfer - session and it can be used to either accept or reject the file - transfer request, by calling the silc_client_file_receive or - silc_client_file_close, respectively. */ - -static void -silc_ftp(SilcClient client, SilcClientConnection conn, - SilcClientEntry client_entry, SilcUInt32 session_id, - const char *hostname, SilcUInt16 port) -{ - -} - - -/* Delivers SILC session detachment data indicated by `detach_data' to the - application. If application has issued SILC_COMMAND_DETACH command - the client session in the SILC network is not quit. The client remains - in the network but is detached. The detachment data may be used later - to resume the session in the SILC Network. The appliation is - responsible of saving the `detach_data', to for example in a file. - - The detachment data can be given as argument to the functions - silc_client_connect_to_server, or silc_client_add_connection when - creating connection to remote server, inside SilcClientConnectionParams - structure. If it is provided the client library will attempt to resume - the session in the network. After the connection is created - successfully, the application is responsible of setting the user - interface for user into the same state it was before detaching (showing - same channels, channel modes, etc). It can do this by fetching the - information (like joined channels) from the client library. */ - -static void -silc_detach(SilcClient client, SilcClientConnection conn, - const unsigned char *detach_data, SilcUInt32 detach_data_len) -{ - -} - -SilcClientOperations ops = { - silc_say, - silc_channel_message, - silc_private_message, - silc_notify, - silc_command, - silc_command_reply, - silc_connected, - silc_disconnected, - silc_get_auth_method, - silc_verify_public_key, - silc_ask_passphrase, - silc_failure, - silc_key_agreement, - silc_ftp, - silc_detach -};