coal._pike
Go to the documentation of this file.
1 /* Copyright (C) 2000-2007 Thomas Bopp, Thorsten Hampel, Ludger Merkens
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * $Id: coal.pike,v 1.2 2009/08/07 15:22:36 nicke Exp $
18  */
19 inherit "coal/protocoll";
20 #include <coal.h>
21 #include <macros.h>
22 #include <assert.h>
23 #include <attributes.h>
24 class coal : public protocoll{
25 public:
26 
27 
28 
29 /*
30  * COAL protocol implementation file
31  */
32 
33 
34 #ifdef COAL_DEBUG
35 #define CDEBUG(s) werror(s+"\n")
36 #else
37 #define CDEBUG(s)
38 #endif
39 
40  mixed mReceiveData;
41  string sLastPacket;
42  array saErrors;
43  int iLastResponse;
44  mapping objectCache;
45 
46 /**
47  * Create the socket and initialize the variables.
48  *
49  */
50 void create()
51 {
52  mCommandServer = ([ ]);
53  sLastPacket = "";
54  iTransfer = COAL_TRANSFER_NONE;
55  iLastResponse = time();
56  objectCache = ([ 0: _Server, ]);
57 
58  saErrors = ({
59  "Object was not found",
60  "COAL: wrong syntax",
61  "COAL: wrong filetype specified",
62  "Security: Access violation",
63  "Target was not found",
64  "Error loading object",
65  "Wrong Password",
66  "account has expired",
67  "Protocol error",
68  "Command not understood",
69  "Execution error (internal server error)",
70  "User is unknown",
71  "Wrong number of arguments to function",
72  "Argument type does not match",
73  "Exception",
74  });
75  init_protocoll();
76 }
77 
78 /**
79  * Called when the socket disconnects and also calls disconnect
80  * function of the user object.
81  *
82  */
83 protected:
84  void
85 disconnect()
86 {
87  CDEBUG("Transfer finished...\n");
88  iTransfer = 0;
89  if ( functionp(oTransfer) ) {
90  oTransfer->close();
91  destruct(oTransfer);
92  oTransfer = 0;
93  }
94  if ( objectp(oUser) )
95  oUser->disconnect();
96 }
97 
98 public:
99 
100 
101 /**
102  * Receive a message on the socket.
103  *
104  * @param string str - the string received on the socket.
105  */
106 protected:
107  void
108 receive_message(string str)
109 {
110  int t_id, obj_id, command;
111  function func;
112  mixed result;
113  array args;
114  array cmds;
115  object obj;
116  int cid, i;
117 
118  iLastResponse = time();
119 
120  str = sLastPacket + str;
121  sLastPacket = "";
122 
123  if ( iTransfer == COAL_TRANSFER_SEND ) {
124  sLastPacket = str;
125  return;
126  }
127  else if ( iTransfer == COAL_TRANSFER_RCV ) {
128  i = strlen(str);
129  if ( iTransferSize != -1 && i > iTransferSize ) {
130  sLastPacket = copy_value(str[iTransferSize..]);
131  str = str[..iTransferSize-1];
132  }
133  oTransfer->write(str);
134  if ( iTransferSize != -1 ) {
135  iTransferSize -= strlen(str);
136  if ( iTransferSize <= 0 ) {
137  oTransfer->close();
138  destruct(oTransfer);
139  oTransfer = 0;
140  str = sLastPacket;
141  iTransfer = COAL_TRANSFER_NONE;
142  }
143  }
144  if ( iTransfer == COAL_TRANSFER_RCV )
145  return;
146  }
147 
148  mixed err = catch(cmds = receive_binary(str));
149 
150  if ( err != 0 ) {
151  // receive binary throws errors with parsed start parameters
152  if ( sizeof(err) > 2 )
153  SEND_ERROR(E_ERROR_PROTOCOL, err[0], err[2], err[4], 0, err[3],
154  ({ }), err[1]);
155  else
156  SEND_ERROR(E_ERROR_PROTOCOL, err[0], 0, 0, 0, 0, ({ }), err[1]);
157  throw(err);
158  }
159 
160  while ( arrayp(cmds) ) {
161  command = cmds[HL_CMD][COALLINE_COMMAND] & COMMAND_RAW;
162  obj_id = cmds[HL_CMD][COALLINE_OBJECT];
163  args = cmds[HL_ARGS];
164  str = cmds[HL_REST];
165  t_id = cmds[HL_CMD][COALLINE_TID];
166  obj = objectCache[obj_id];
167  if (!objectp(obj)) {
168  obj = find_object(obj_id);
169  objectCache[obj_id] = obj;
170  }
171 
172  func = mCommandServer[command];
173  cid = (objectp(obj) ? obj->get_object_class() : 0);
174 
175  CDEBUG("RCVD: " + command + ","+obj_id+","+t_id+")");
176  if ( functionp(func) )
177  {
178  mixed message = catch {
179  result = func(t_id, obj, args);
180  };
181  if ( message != 0 )
182  iTransfer = 0; // set back transfer mode !
183  if ( arrayp(message) ) {
184  if ( sizeof(message) == 3 ) {
185  SEND_ERROR(message[2], message[0], t_id, obj_id, cid,
186  command, args,
187  master()->describe_backtrace(message[1]));
188  }
189  else {
190  FATAL(message[0]);
191  FATAL(master()->describe_backtrace(message[1]));
192  SEND_ERROR(E_ERROR, message[0],
193  t_id, obj_id, cid, command, args,
194  master()->describe_backtrace(message[1]));
195  }
196  }
197  else if ( objectp(message) ) {
198  if ( !functionp(message->display) ) {
199  FATAL(message[0]);
200  FATAL(master()->describe_backtrace(message[1]));
201  }
202  SEND_ERROR(E_ERROR, message[0],
203  t_id, obj_id, cid, command, args,
204  master()->describe_backtrace(message[1]));
205  }
206 
207  if ( result != 0 ) {
208  SEND_ERROR(result, "Exception",t_id,obj_id,cid,
209  command, args, 0);
210  }
211  }
212  else
213  SEND_ERROR(E_FUNCTION|E_NOTEXIST, "Command does not exist !",
214  t_id, obj_id, cid,command, args, 0);
215  cmds = receive_binary(str);
216  }
217  sLastPacket = str;
218 }
219 
220 public:
221 
222 void hangup()
223 {
224  SEND_COAL(0, COAL_LOGOUT, 0, 0, ({ }));
225  close_connection();
226 }
227 
228 protected:
229  void close_connection()
230 {
231  logout_user();
232 }
233 
234 public:
235 
236 string get_socket_name() { return "coal"; }
237 int get_last_response() { return iLastResponse; }
238 
239 
240 };