server_side.cpp

Go to the documentation of this file.
00001 /*****************************************************************************\
00002 *                                                                             *
00003 *  Name   : example rpc server                                                *
00004 *  Author : Chris Koeritz                                                     *
00005 *                                                                             *
00006 *******************************************************************************
00007 * Copyright (c) 1995-$now By Author.  This program is free software; you can  *
00008 * redistribute it and/or modify it under the terms of the GNU General Public  *
00009 * License as published by the Free Software Foundation; either version 2 of   *
00010 * the License or (at your option) any later version.  This is online at:      *
00011 *     http://www.fsf.org/copyleft/gpl.html                                    *
00012 * Please send any updates to: fred@gruntose.com                               *
00013 \*****************************************************************************/
00014 
00015 #include "implem_only.h"
00016 #include "server_side.h"
00017 
00018 #include <opsystem/path_configuration.h>
00019 #include <geometric/point.cpp>
00020 
00022 
00023 // pries the "to_detach" object off of an array called "data" and if this
00024 // cannot be done, it complains and returns "to_return".
00025 #define DETACH(to_detach, to_return) { \
00026   if (!detach(data, (int &)to_detach)) { \
00027     LOG("detach failed on " #to_detach); \
00028     return to_return; \
00029   } \
00030 }
00031 
00033 
00034 const int MAX_CLIENTS = 10;
00035   // maximum number of simultaneous client calls.
00036 const int MAX_SLUSH = 15;
00037   // this is the number of extra calls that could occur even though the limit
00038   // is set above.  the limits are "recommendations" according to MS docs;
00039   // the slush keeps things from blowing up, hopefully.
00040 
00042 
00043 example_rpc_server *single_server_instance = NIL;
00044 
00045 example_rpc_server::example_rpc_server(CFrameWnd *parent, window_handle _alert)
00046 : alert(_alert),
00047   ng_rpc_server(),
00048   mouser(new drawing_window(*this))
00049 {
00050   mouser->Create(parent, "server win", _alert, true);
00051 //attempt to show it.  mouser->ShowWindow(SW_RESTORE);
00053   begin_service();
00054   single_server_instance = this;
00055 }
00056 
00057 example_rpc_server::~example_rpc_server()
00058 {
00059   single_server_instance = NIL;
00060   stop_accepting();
00061   shut_down();
00062   mouser->be_gone();
00064 }
00065 
00066 byte_array example_rpc_server::register_client(const byte_array &_data)
00067 {
00068   FUNCDEF("register_client");
00069   byte_array data(_data);
00070   window_handle new_client;
00071   DETACH(new_client, byte_array());
00072   client_record to_add;
00073   to_add.window = new_client;
00074   mouser->lock();
00075   client_list += to_add;
00076   mouser->unlock();
00077   return byte_array();
00078 }
00079 
00080 byte_array example_rpc_server::unregister_client(const byte_array &_data)
00081 {
00082   FUNCDEF("unregister_client");
00083   byte_array data(_data);
00084   window_handle old_client;
00085   DETACH(old_client, byte_array());
00086   mouser->lock();
00087   for (int i = 0; i < client_list.length(); i++) {
00088     if (client_list[i].window == old_client) {
00089       client_list.zap(i, i);
00090       mouser->unlock();
00091       return byte_array();
00092     }
00093   }
00094   mouser->unlock();
00095   LOG(istring(istring::SPRINTF, "client to whack (%d) not "
00096       "found!", old_client));
00097   return byte_array();
00098 }
00099 
00100 byte_array example_rpc_server::add_point(const byte_array &data)
00101 {
00102   array<rpc_point> found;
00103   mouser->pull_out_mice(data, found);
00104   for (int i = 0; i < found.length(); i++) mouser->add_dot(found[i]);
00105   mouser->start_timer(50);
00106   return byte_array();
00107 }
00108 
00109 byte_array example_rpc_server::get_entire_list(const byte_array &formal(data))
00110 {
00111   byte_array to_return;
00112   array<rpc_point> the_list;
00113   mouser->get_mouse_list(the_list);
00114   mouser->push_in_mice(the_list, to_return);
00115   return to_return;
00116 }
00117 
00118 byte_array example_rpc_server::get_partial_list(const byte_array &_data)
00119 {
00120   FUNCDEF("get_partial_list");
00121   byte_array data(_data);
00122   int index;
00123   DETACH(index, byte_array());
00124   LOG(istring(istring::SPRINTF, "got a request starting at index %d, where our list goes to %d.",
00125       index, mouser->length()));
00126   // get the full mouse list.
00127   array<rpc_point> meese;
00128   mouser->get_mouse_list(meese);
00129   // chop the entries they don't care about.
00130   meese.zap(0, index - 1);
00131   // stuff the list into a block to return.
00132   byte_array to_return;
00133   mouser->push_in_mice(meese, to_return);
00134   return to_return;
00135 }
00136 
00137 void example_rpc_server::update()
00138 {
00139   FUNCDEF("update");
00140   mouser->lock();
00141   LOG(istring(istring::SPRINTF, "updating %d clients...", client_list.length()));
00142   for (int i = 0; i < client_list.length(); i++)
00143     PostMessage(client_list[i].window, POINT_ALERT(), 0, 0);
00144   mouser->unlock();
00145 }
00146 
00147 void example_rpc_server::mouse_hit(const rpc_point &position)
00148 {
00149   FUNCDEF("mouse_hit");
00150   mouser->add_dot(position);
00151   mouser->start_timer(50);
00152   LOG("got a hit, started timer.");
00153 }
00154 
00155 void example_rpc_server::process_client_request(const char *_transaction_name,
00156     const rpc_data_block &request, rpc_data_block &response)
00157 {
00158   FUNCDEF("process_client_request");
00159   istring to_print(istring::SPRINTF, "request %s came with %d bytes of data.",
00160       _transaction_name, request.length);
00161   LOG(to_print);
00162 
00163   byte_array passed(request.length, request.data);
00164 
00165   byte_array found;
00166   istring transaction_name = _transaction_name;
00167   if (transaction_name == REGISTER_CLIENT) {
00168     found = register_client(passed);
00169   } else if (transaction_name == UNREGISTER_CLIENT) {
00170     found = unregister_client(passed);
00171   } else if (transaction_name == NEW_POINT) {
00172     found = add_point(passed);
00173   } else if (transaction_name == GET_LIST) {
00174     found = get_entire_list(passed);
00175   } else if (transaction_name == GET_PARTIAL) {
00176     found = get_partial_list(passed);
00177   } else {
00178     LOG(istring("unknown request: ") + transaction_name);
00179   }
00180 
00181   // if the reply is too big, truncate it to the given length.
00182   if (found.length() > response.length) {
00183     found.zap(response.length - 1, found.length() - 1);
00184     LOG("response too big for passed storage.  truncating it.");
00185   }
00186 
00187   // store the reply.
00188   found.stuff(found.length(), response.data);
00189   response.length = found.length();
00190 }
00191 
00193 
00194 /*
00195 void example_rpc_server::server_thread(void *hidden_pointer)
00196 {
00197   FUNCDEF("server_thread");
00198   #define alert the_server->alert
00199   example_rpc_server *the_server = (example_rpc_server *)hidden_pointer;
00200   rpc_common::outcomes outcome = the_server->setup(MAX_CLIENTS,
00201       rpc_common::LOCAL, "1", "");
00202   if (outcome != rpc_common::OKAY)
00203     KABOOM(istring("problem setting up rpc server: ")
00204         + rpc_common::outcome_name(outcome));
00205 
00206 // question: does the maximum calls number have to be lower than the maximum
00207 // number that was established above?
00208   outcome = the_server->accept_clients(1, MAX_CLIENTS + MAX_SLUSH, true);
00209     // at least one client must connect for service to be granted, the maximum
00210     // number of clients at once is specified by the configuration above,
00211     // and wait for clients to be serviced (don't return from thread until
00212     // server stops listening).
00213   if (outcome != rpc_common::OKAY)
00214     KABOOM(istring("problem accepting clients: ")
00215         + rpc_common::outcome_name(outcome));
00216   #undef alert
00217 }
00218 */
00219 
00221 
00222 // this is the root communication function between server and clients.
00223 int named_byte_transaction(handle_t h, const byte *service, const byte *topic,
00224     int uid, const rpc_data_block *request, rpc_data_block *response)
00225 {
00226   FUNCDEF("named_byte_transaction");
00227   if (!single_server_instance) {
00228     MessageBox(0, "named_byte_transaction has no server!", "Yikes!",
00229         MB_OK | MB_ICONWARNING);
00230     return 0;
00231   }
00232   if (!request || !response) {
00233     MessageBox(0, "named_byte_transaction got a nil data block!", "Yikes!",
00234         MB_OK | MB_ICONWARNING);
00235     return 0;
00236   }
00237   single_server_instance->process_client_request((char *)topic, *request,
00238       *response);
00239   return 0;
00240 }
00241 
00242 int ng_login(handle_t h, const byte *entity, int root_id, int *id)
00243 { return NG_RPC_OKAY; }
00244 
00245 int ng_logout(handle_t h, int id) { return NG_RPC_OKAY; }
00246 

Generated on Fri Nov 28 04:29:33 2008 for HOOPLE Libraries by  doxygen 1.5.1