/*******************************************************************************
* Copyright (c) 2007, 2008 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Wind River Systems - initial API and implementation
*******************************************************************************/
/*
* Agent main module.
*/
#include "mdep.h"
#define CONFIG_MAIN
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <signal.h>
#include "asyncreq.h"
#include "events.h"
#include "trace.h"
#include "myalloc.h"
#include "expressions.h"
#include "cmdline.h"
#include "context.h"
#include "channel.h"
#include "protocol.h"
#include "discovery.h"
#include "test.h"
static char * progname;
static Protocol * proto;
static ChannelServer * serv;
static ChannelServer * serv2;
static TCFBroadcastGroup * bcg;
static TCFSuspendGroup * spg;
static void channel_server_connecting(Channel * c) {
trace(LOG_PROTOCOL, "channel server connecting");
send_hello_message(c->client_data, c);
discovery_channel_add(c);
c->out.flush(&c->out);
}
static void channel_server_connected(Channel * c) {
int i;
trace(LOG_PROTOCOL, "channel server connected, peer services:");
for (i = 0; i < c->peer_service_cnt; i++) {
trace(LOG_PROTOCOL, " %s", c->peer_service_list[i]);
}
}
static void channel_server_receive(Channel * c) {
handle_protocol_message(c->client_data, c);
}
static void channel_server_disconnected(Channel * c) {
trace(LOG_PROTOCOL, "channel server disconnected");
discovery_channel_remove(c);
protocol_channel_closed(c->client_data, c);
}
static void channel_new_connection(ChannelServer * serv, Channel * c) {
protocol_reference(proto);
c->client_data = proto;
c->connecting = channel_server_connecting;
c->connected = channel_server_connected;
c->receive = channel_server_receive;
c->disconnected = channel_server_disconnected;
channel_set_suspend_group(c, spg);
channel_set_broadcast_group(c, bcg);
channel_start(c);
protocol_channel_opened(proto, c);
}
static void became_discovery_master(void) {
PeerServer * ps = channel_peer_from_url(DEFAULT_DISCOVERY_URL);
if (ps == NULL) {
trace(LOG_ALWAYS, "cannot parse url: %s\n", DEFAULT_DISCOVERY_URL);
return;
}
serv2 = channel_server(ps);
if (serv2 == NULL) {
trace(LOG_ALWAYS, "cannot create second TCF server\n");
return;
}
serv2->new_conn = channel_new_connection;
}
#if defined(_WRS_KERNEL)
int tcf(void) {
#else
int main(int argc, char ** argv) {
#endif
int c;
int ind;
int ismaster;
int interactive = 0;
char * s;
char * log_name = 0;
char * url = "TCP:";
PeerServer * ps;
#ifndef WIN32
signal(SIGPIPE, SIG_IGN);
#endif
ini_mdep();
ini_trace();
ini_asyncreq();
#if defined(_WRS_KERNEL)
progname = "tcf";
open_log_file("-");
log_mode = 0;
#else
progname = argv[0];
/* Parse arguments */
for (ind = 1; ind < argc; ind++) {
s = argv[ind];
if (*s != '-') {
break;
}
s++;
while ((c = *s++) != '\0') {
switch (c) {
case 'i':
interactive = 1;
break;
case 't':
test_proc();
exit(0);
break;
case 'l':
case 'L':
case 's':
if (*s == '\0') {
if (++ind >= argc) {
fprintf(stderr, "%s: error: no argument given to option '%c'\n", progname, c);
exit(1);
}
s = argv[ind];
}
switch (c) {
case 'l':
log_mode = strtol(s, 0, 0);
break;
case 'L':
log_name = s;
break;
case 's':
url = s;
break;
default:
fprintf(stderr, "%s: error: illegal option '%c'\n", progname, c);
exit(1);
}
s = "";
break;
default:
fprintf(stderr, "%s: error: illegal option '%c'\n", progname, c);
exit(1);
}
}
}
open_log_file(log_name);
#endif
ini_events_queue();
ini_expression_library();
bcg = broadcast_group_alloc();
spg = suspend_group_alloc();
proto = protocol_alloc();
ini_locator_service(proto);
ini_services(proto, bcg, spg);
ini_contexts();
ismaster = discovery_start(became_discovery_master);
ps = channel_peer_from_url(url);
if (ps == NULL) {
fprintf(stderr, "invalid server URL (-s option value): %s\n", url);
exit(1);
}
if (ismaster) {
if (!strcmp(peer_server_getprop(ps, "TransportName", ""), "TCP") &&
peer_server_getprop(ps, "Port", NULL) == NULL) {
peer_server_addprop(ps, loc_strdup("Port"), loc_strdup(DISCOVERY_TCF_PORT));
}
serv = channel_server(ps);
/* TODO: replace 'ps' with actual peer object created for the server */
if (strcmp(peer_server_getprop(ps, "TransportName", ""), "TCP") ||
strcmp(peer_server_getprop(ps, "Port", ""), DISCOVERY_TCF_PORT)) {
became_discovery_master();
}
}
else {
serv = channel_server(ps);
}
if (serv == NULL) {
fprintf(stderr, "cannot create TCF server\n");
exit(1);
}
serv->new_conn = channel_new_connection;
if (interactive) ini_cmdline_handler();
/* Process events - must run on the initial thread since ptrace()
* returns ECHILD otherwise, thinking we are not the owner. */
run_event_loop();
return 0;
}