File: Server.pike

package info (click to toggle)
pike8.0 8.0.1956-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 60,580 kB
  • sloc: ansic: 259,734; xml: 36,320; makefile: 3,748; sh: 1,713; cpp: 1,349; awk: 1,036; lisp: 655; javascript: 468; asm: 242; objc: 240; pascal: 157; sed: 34
file content (136 lines) | stat: -rw-r--r-- 2,880 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#pike __REAL_VERSION__
#include "remote.h"
import ".";

//! Remote RPC server.

int portno;

//! @decl Stdio.Port port
//!
//! Port for the @[Remote.Server].
object port;

//! @decl array(Connection) connections
//!
//! Open connections.
array connections = ({ });

//! @decl Minicontext sctx
//!
//! Server context.
object sctx;

int max_call_threads;

//! The server @[Context] class.
class Minicontext
{
  mapping(string:mixed) id2val = ([ ]);
  mapping(mixed:string) val2id = ([ ]);

  string id_for(mixed thing)
  {
    return val2id[thing];
  }

  object object_for(string id, object con)
  {
    object o = id2val[id];
    if(functionp(o) || programp(o))
      o = o(con);
    if(objectp(o) && functionp(o->close))
      con->add_close_callback(o->close);
    return o;
  }

  void add(string name, object|program what)
  {
    id2val[name] = what;
    val2id[what] = name;
  }
}

void got_connection(object f)
{
  object c = f->accept();
  c->set_blocking();
  object con = Connection(0, max_call_threads);
  object ctx = Context(gethostname()+"-"+portno);
  if (!c)
    error("Failed to accept connection: %s\n", strerror (f->errno()));
  con->start_server(c, ctx);
  ctx->set_server_context(sctx, con);
  connections += ({ con });
}

//! @decl void create(string host, int port, void|int max_call_threads)
//! Create a @[Remote.Server].
//!
//! @param host
//! @param port
//!   Hostname and port for the @[Remote.Server].
//!
//! @param max_call_threads
//!   Maximum number of concurrent threads.
void create(string host, int p, void|int _max_call_threads)
{
  portno = p;
  max_call_threads = _max_call_threads;
  port = Stdio.Port();
  port->set_id(port);
  if(host)
  {
    if(!port->bind(p, got_connection, host))
      error("Failed to bind port: %s\n", strerror (port->errno()));
  }
  else if(!port->bind(p, got_connection))
    error("Failed to bind port: %s\n", strerror (port->errno()));

  DEBUGMSG("listening to " + host + ":" + p + "\n");

  if(!portno)
    sscanf(port->query_address(), "%*s %d", portno);

  sctx = Minicontext();
}

//! Provide a named @[thing] to the @[Remote.Client](s).
//!
//! @param name
//!   Name to provide @[thing] under.
//!
//! @param thing
//!   Thing to provide.
void provide(string name, mixed thing)
{
  DEBUGMSG("providing "+name+"\n");
  sctx->add(name, thing);
}

//! Shut down the @[Remote.Server] for new connections.
void close()
{
  DEBUGMSG("closing listening port\n");
  destruct (port);
}

//! Shut down the @[Remote.Server] and terminate all current clients.
void close_all()
{
  DEBUGMSG("closing listening port and all connections\n");
  destruct (port);
  foreach (connections, object conn) conn->close();
}

//! Check if the @[Remote.Server] is closed.
int closed()
{
  return !!port;
}

void destroy()
{
  DEBUGMSG("destruct" + (port ? " - closing listening port\n" : "\n"));
  catch (destruct (port));
}