replace C API by Lua

Signed-off-by: zhaojh329 <jianhuizhao329@gmail.com>
This commit is contained in:
zhaojh329
2017-06-06 01:02:30 +08:00
parent c2dd25a03a
commit a637ff7b5d
11 changed files with 6700 additions and 738 deletions
-15
View File
@@ -1,15 +0,0 @@
cmake_minimum_required (VERSION 2.6)
project(xterminal C)
add_definitions(-O -Wall -Werror --std=gnu99 -g3)
add_executable(xterminal_device xterminal_device.c)
add_executable(xterminal_broker xterminal_broker.c)
target_link_libraries(xterminal_broker ev evmongoose)
target_link_libraries(xterminal_device ev util evmongoose)
install(TARGETS xterminal_device xterminal_broker
RUNTIME DESTINATION bin
)
-9
View File
@@ -1,9 +0,0 @@
#ifndef __COMMON_H_
#define __COMMON_H_
#include "list.h"
int asprintf(char **strp, const char *fmt, ...);
void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);
#endif
Vendored Executable
+5
View File
File diff suppressed because one or more lines are too long
-208
View File
@@ -1,208 +0,0 @@
/*-
* Copyright (c) 2011 Felix Fietkau <nbd@openwrt.org>
* Copyright (c) 2010 Isilon Systems, Inc.
* Copyright (c) 2010 iX Systems, Inc.
* Copyright (c) 2010 Panasas, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LINUX_LIST_H_
#define _LINUX_LIST_H_
#include <stddef.h>
#include <stdbool.h>
#define prefetch(x)
#ifndef container_of
#define container_of(ptr, type, member) \
({ \
const typeof(((type *) NULL)->member) *__mptr = (ptr); \
(type *) ((char *) __mptr - offsetof(type, member)); \
})
#endif
struct list_head {
struct list_head *next;
struct list_head *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#undef LIST_HEAD
#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)
static inline void
INIT_LIST_HEAD(struct list_head *list)
{
list->next = list->prev = list;
}
static inline bool
list_empty(const struct list_head *head)
{
return (head->next == head);
}
static inline bool
list_is_first(const struct list_head *list,
const struct list_head *head)
{
return list->prev == head;
}
static inline bool
list_is_last(const struct list_head *list,
const struct list_head *head)
{
return list->next == head;
}
static inline void
_list_del(struct list_head *entry)
{
entry->next->prev = entry->prev;
entry->prev->next = entry->next;
}
static inline void
list_del(struct list_head *entry)
{
_list_del(entry);
entry->next = entry->prev = NULL;
}
static inline void
_list_add(struct list_head *_new, struct list_head *prev,
struct list_head *next)
{
next->prev = _new;
_new->next = next;
_new->prev = prev;
prev->next = _new;
}
static inline void
list_del_init(struct list_head *entry)
{
_list_del(entry);
INIT_LIST_HEAD(entry);
}
#define list_entry(ptr, type, field) container_of(ptr, type, field)
#define list_first_entry(ptr, type, field) list_entry((ptr)->next, type, field)
#define list_last_entry(ptr, type, field) list_entry((ptr)->prev, type, field)
#define list_for_each(p, head) \
for (p = (head)->next; p != (head); p = p->next)
#define list_for_each_safe(p, n, head) \
for (p = (head)->next, n = p->next; p != (head); p = n, n = p->next)
#define list_for_each_entry(p, h, field) \
for (p = list_first_entry(h, typeof(*p), field); &p->field != (h); \
p = list_entry(p->field.next, typeof(*p), field))
#define list_for_each_entry_safe(p, n, h, field) \
for (p = list_first_entry(h, typeof(*p), field), \
n = list_entry(p->field.next, typeof(*p), field); &p->field != (h);\
p = n, n = list_entry(n->field.next, typeof(*n), field))
#define list_for_each_entry_reverse(p, h, field) \
for (p = list_last_entry(h, typeof(*p), field); &p->field != (h); \
p = list_entry(p->field.prev, typeof(*p), field))
#define list_for_each_prev(p, h) for (p = (h)->prev; p != (h); p = p->prev)
#define list_for_each_prev_safe(p, n, h) for (p = (h)->prev, n = p->prev; p != (h); p = n, n = p->prev)
static inline void
list_add(struct list_head *_new, struct list_head *head)
{
_list_add(_new, head, head->next);
}
static inline void
list_add_tail(struct list_head *_new, struct list_head *head)
{
_list_add(_new, head->prev, head);
}
static inline void
list_move(struct list_head *list, struct list_head *head)
{
_list_del(list);
list_add(list, head);
}
static inline void
list_move_tail(struct list_head *entry, struct list_head *head)
{
_list_del(entry);
list_add_tail(entry, head);
}
static inline void
_list_splice(const struct list_head *list, struct list_head *prev,
struct list_head *next)
{
struct list_head *first;
struct list_head *last;
if (list_empty(list))
return;
first = list->next;
last = list->prev;
first->prev = prev;
prev->next = first;
last->next = next;
next->prev = last;
}
static inline void
list_splice(const struct list_head *list, struct list_head *head)
{
_list_splice(list, head, head->next);
}
static inline void
list_splice_tail(struct list_head *list, struct list_head *head)
{
_list_splice(list, head->prev, head);
}
static inline void
list_splice_init(struct list_head *list, struct list_head *head)
{
_list_splice(list, head, head->next);
INIT_LIST_HEAD(list);
}
static inline void
list_splice_tail_init(struct list_head *list, struct list_head *head)
{
_list_splice(list, head->prev, head);
INIT_LIST_HEAD(list);
}
#endif /* _LINUX_LIST_H_ */
+32 -27
View File
@@ -1,27 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Websocket Test</title>
</head>
<body>
<button type="button" onclick="connect()">Connect</button>
<script>
function connect() {
var ws = new WebSocket("ws://" + location.host);
ws.onopen = function() {
console.log("connect ok");
ws.send("Hello WebSocket");
};
ws.onmessage = function (evt) {
console.log("recv:"+evt.data);
};
ws.onclose = function() {
console.log("close");
};
}
</script>
</body>
</html>
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="xterm.css" />
<script src="jquery-1.12.4.min.js"></script>
<script src="xterm.js"></script>
<script src="utf8.js"></script>
</head>
<body>
<div id="terminal"></div>
<script>
var ws = new WebSocket("ws://" + location.host);
var term = new Terminal();
ws.onopen = function() {
term.open(document.getElementById('terminal'));
ws.send("connect 448A5BEC4927");
term.on('data', function(data) {
ws.send(data);
});
};
ws.onmessage = function (e) {
term.write(e.data);
};
</script>
</body>
</html>
Executable
+2247
View File
File diff suppressed because it is too large Load Diff
Executable
+4219
View File
File diff suppressed because it is too large Load Diff
-254
View File
@@ -1,254 +0,0 @@
#include <mongoose.h>
#include <termios.h>
#include "common.h"
static LIST_HEAD(device_list);
static LIST_HEAD(session_list);
struct device {
char mac[13];
int alive;
struct list_head node;
};
struct session {
char id[33];
struct device *dev;
struct list_head node;
struct mg_connection *nc;
};
static struct session *find_session_by_nc(struct mg_connection *nc)
{
struct session *s = NULL;
list_for_each_entry(s, &session_list, node) {
if (s->nc == nc)
return s;
}
return NULL;
}
static struct device *find_device_by_mac(struct mg_str *mac)
{
struct device *dev = NULL;
list_for_each_entry(dev, &device_list, node) {
if (!mg_vcmp(mac, dev->mac))
return dev;
}
return NULL;
}
static void update_device(struct mg_str *mac)
{
struct device *dev = find_device_by_mac(mac);
if (!dev) {
dev = calloc(1, sizeof(struct device));
if (!dev) {
perror("calloc");
return;
}
list_add(&dev->node, &device_list);
strncpy(dev->mac, mac->p, mac->len);
}
dev->alive = 10;
}
static struct session *session_new(struct mg_connection *nc, struct mg_str *mac)
{
char buf[128] = "";
struct timeval tv;
struct session *s = NULL;
struct device *dev = NULL;
dev = find_device_by_mac(mac);
if (!dev)
return NULL;
s = calloc(1, sizeof(struct session));
if (!s) {
perror("calloc");
return NULL;
}
list_add(&s->node, &session_list);
s->dev = dev;
gettimeofday(&tv, NULL);
snprintf(buf, sizeof(buf), "%ld", tv.tv_sec * 1000 + tv.tv_usec / 1000);
cs_md5(s->id, buf, strlen(buf), NULL);
s->nc = nc;
printf("new session:%s\n", s->id);
return s;
}
static struct mg_connection *mqtt_nc;
static struct mg_connection *websocket_nc;
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data)
{
if (ev == MG_EV_CONNECT) {
/* Connect to mqtt broker */
struct mg_send_mqtt_handshake_opts opts;
memset(&opts, 0, sizeof(opts));
mg_set_protocol_mqtt(nc);
mg_send_mqtt_handshake_opt(nc, "xxxx12342", opts);
} else if (ev == MG_EV_MQTT_CONNACK) {
struct mg_mqtt_message *msg = (struct mg_mqtt_message *)ev_data;
struct mg_mqtt_topic_expression topic_expr[1];
if (msg->connack_ret_code != MG_EV_MQTT_CONNACK_ACCEPTED) {
printf("Got mqtt connection error: %d\n", msg->connack_ret_code);
ev_break(EV_DEFAULT, EVBREAK_ALL);
return;
}
topic_expr[0].qos = MG_MQTT_QOS(0);
asprintf((char **)&topic_expr[0].topic, "xterminal/heartbeat");
mg_mqtt_subscribe(nc, topic_expr, 1, 0);
free((char *)topic_expr[0].topic);
mqtt_nc = nc;
} else if (ev == MG_EV_MQTT_PUBLISH) {
struct mg_mqtt_message *msg = (struct mg_mqtt_message *)ev_data;
if (!mg_vcmp(&msg->topic, "xterminal/heartbeat")) {
update_device(&msg->payload);
} else if (memmem(msg->topic.p, msg->topic.len, "devdata", strlen("devdata"))) {
mg_send_websocket_frame(websocket_nc, WEBSOCKET_OP_TEXT, msg->payload.p, msg->payload.len);
}
} else if (ev == MG_EV_HTTP_REQUEST) {
struct http_message *hm = (struct http_message *)ev_data;
if (!mg_vcmp(&hm->uri, "/list")) {
struct device *dev;
mg_send_head(nc, 200, -1, NULL);
mg_printf_http_chunk(nc, "[");
list_for_each_entry(dev, &device_list, node) {
mg_printf_http_chunk(nc, "\"%s\",", dev->mac);
}
mg_printf_http_chunk(nc, "\"\"]");
mg_send_http_chunk(nc, "", 0);
} else {
struct mg_serve_http_opts opts = {};
mg_serve_http(nc, hm, opts);
}
} else if (ev == MG_EV_WEBSOCKET_HANDSHAKE_DONE) {
websocket_nc = nc;
} else if (ev == MG_EV_WEBSOCKET_FRAME) {
struct websocket_message *wm = (struct websocket_message *)ev_data;
if (wm->flags & WEBSOCKET_OP_TEXT) {
const char *pattern = "connect ????????????";
const struct mg_str pstr = {pattern, strlen(pattern)};
if (mg_match_prefix_n(pstr, mg_mk_str_n((const char *)wm->data, wm->size)) > 0) {
char topic[128] = "";
struct mg_mqtt_topic_expression topic_expr[1];
struct mg_str mac = mg_mk_str_n((const char *)(wm->data + 8), wm->size - 8);
struct session *s = session_new(nc, &mac);
if (!s)
return;
topic_expr[0].qos = MG_MQTT_QOS(0);
asprintf((char **)&topic_expr[0].topic, "xterminal/%.*s/%s/devdata", (int)mac.len, mac.p, s->id);
mg_mqtt_subscribe(mqtt_nc, topic_expr, 1, 44);
free((char *)topic_expr[0].topic);
sprintf(topic, "xterminal/%.*s/connect/%s", (int)mac.len, mac.p, s->id);
mg_mqtt_publish(mqtt_nc, topic, 0, MG_MQTT_QOS(0), NULL, 0);
} else {
char topic[128] = "";
struct session *s = find_session_by_nc(nc);
sprintf(topic, "xterminal/%s/%s/srvdata", s->dev->mac, s->id);
mg_mqtt_publish(mqtt_nc, topic, 0, MG_MQTT_QOS(0), wm->data, wm->size);
printf("pub to:%s %.*s\n", topic, (int)wm->size, wm->data);
}
}
} else if (ev == MG_EV_CLOSE) {
//printf("connection close:%p\n", nc);
}
}
static void device_alive_cb(struct ev_loop *loop, ev_timer *w, int revents)
{
struct device *dev, *tmp;
list_for_each_entry_safe(dev, tmp, &device_list, node) {
if (dev->alive-- == 0) {
printf("del timeout device:%s\n", dev->mac);
list_del(&dev->node);
free(dev);
}
}
}
static void signal_cb(struct ev_loop *loop, ev_signal *w, int revents)
{
printf("Got signal: %d\n", w->signum);
ev_break(loop, EVBREAK_ALL);
}
int main(int argc, char *argv[])
{
struct ev_loop *loop = EV_DEFAULT;
ev_signal sig_watcher;
struct mg_mgr mgr;
struct mg_connection *nc;
const char *s_address = "localhost:1883";
const char *s_http_port = "8000";
ev_timer device_timer;
ev_signal_init(&sig_watcher, signal_cb, SIGINT);
ev_signal_start(loop, &sig_watcher);
ev_timer_init(&device_timer, device_alive_cb, 0.1, 2.0);
ev_timer_start(loop, &device_timer);
mg_mgr_init(&mgr, NULL);
nc = mg_connect(&mgr, s_address, ev_handler);
if (!nc) {
fprintf(stderr, "mg_connect(%s) failed\n", s_address);
}
nc = mg_bind(&mgr, s_http_port, ev_handler);
if (nc == NULL) {
printf("Failed to create listener\n");
return 1;
}
mg_set_protocol_http_websocket(nc);
ev_run(loop, 0);
printf("exit...\n");
mg_mgr_free(&mgr);
return 0;
}
+114
View File
@@ -0,0 +1,114 @@
#!/usr/bin/lua
local ev = require("ev")
local evmg = require("evmongoose")
local posix = require 'posix'
local cjson = require("cjson")
local loop = ev.Loop.default
local mgr = evmg.init()
local device = {}
local session = {}
local function find_sid_by_websocket(nc)
for k, v in pairs(session) do
if v.websocket_nc == nc then
return k
end
end
return nil
end
local function ev_handle(nc, event, msg)
if event == evmg.MG_EV_CONNECT then
mgr:set_protocol_mqtt(nc)
mgr:send_mqtt_handshake_opt(nc)
elseif event == evmg.MG_EV_MQTT_CONNACK then
if msg.connack_ret_code ~= evmg.MG_EV_MQTT_CONNACK_ACCEPTED then
print("Got mqtt connection error:", msg.connack_ret_code)
return
end
mgr:mqtt_subscribe(nc, "xterminal/heartbeat");
ev.Timer.new(function(loop, timer, revents)
for k, v in pairs(device) do
v.alive = v.alive - 1
if v.alive == 0 then
device[k] = nil
print("timeout:", k)
end
end
end, 1, 3):start(loop)
elseif event == evmg.MG_EV_MQTT_PUBLISH then
local topic = msg.topic
print("mqtt recv:", topic)
if topic == "xterminal/heartbeat" then
local mac = msg.payload
if not device[mac] then
device[mac] = {}
print("new dev:", mac)
end
device[mac] = {alive = 5, mqtt_nc = nc}
elseif topic:match("devdata") then
local mac, sid = topic:match("xterminal/(%w+)/(%w+)/devdata")
mgr:send_websocket_frame(session[sid].websocket_nc, msg.payload)
end
elseif event == evmg.MG_EV_HTTP_REQUEST then
local uri = msg.uri
if uri == "/list" then
mgr:send_head(nc, 200, -1)
local devs = {}
for k, v in pairs(device) do
devs[#devs + 1] = k
end
mgr:print_http_chunk(nc, cjson.encode(devs))
mgr:print_http_chunk(nc, "")
return true
end
elseif event == evmg.MG_EV_WEBSOCKET_FRAME then
local data = msg.data
if data:match("connect ") then
local mac = data:match("connect (%w+)")
local sid = "fsdg23423"
session[sid] = {
websocket_nc = nc,
mac = mac
}
mgr:mqtt_subscribe(device[mac].mqtt_nc, "xterminal/" .. mac .. "/" .. sid .. "/devdata");
mgr:mqtt_publish(device[mac].mqtt_nc, "xterminal/" .. mac .. "/connect/" .. sid, "");
else
local sid = find_sid_by_websocket(nc)
local s = session[sid]
mgr:mqtt_publish(device[s.mac].mqtt_nc, "xterminal/" .. s.mac .. "/" .. sid .. "/srvdata", msg.data);
end
end
end
mgr:connect("localhost:1883", ev_handle)
mgr:bind("8000", ev_handle, {proto = "http"})
print("Listen on http 8000...")
ev.Signal.new(function(loop, sig, revents)
loop:unloop()
end, ev.SIGINT):start(loop)
print("start...")
loop:loop()
mgr:destroy()
print("exit...")
-225
View File
@@ -1,225 +0,0 @@
#include <mongoose.h>
#include <pty.h>
#include <net/if.h>
#include "common.h"
struct session {
pid_t pid;
int pty;
char id[33];
struct list_head node;
ev_io watcher;
char topic_dev[128];
char topic_srv[128];
struct mg_connection *nc;
};
static char *devid;
static LIST_HEAD(session_list);
static void pty_read_cb(struct ev_loop *loop, ev_io *w, int revents)
{
int len = 0;
char buf[1024] = "";
struct session *s = (struct session *)w->data;
len = read(w->fd, buf, sizeof(buf));
if (len > 0) {
mg_mqtt_publish(s->nc, s->topic_dev, 0, MG_MQTT_QOS(0), buf, len);
printf("pub to:%s %s\n", s->topic_dev, buf);
} else {
perror("read");
ev_io_stop(loop, w);
}
}
static struct session *find_session_by_id(char *id)
{
struct session *s = NULL;
list_for_each_entry(s, &session_list, node) {
if (!strcmp(s->id, id))
return s;
}
return NULL;
}
static void new_connect(struct mg_connection *nc, char *id)
{
struct session *s = NULL;
pid_t pid;
int pty;
struct mg_mqtt_topic_expression topic_expr[1];
pid = forkpty(&pty, NULL, NULL, NULL);
if (pid < 0) {
perror("forkpty");
return;
} else if (pid == 0) {
execl("/bin/login", "login", NULL);
}
s = calloc(1, sizeof(struct session));
if (!s) {
perror("calloc");
return;
}
list_add(&s->node, &session_list);
strncpy(s->id, id, sizeof(s->id));
s->pid = pid;
s->pty = pty;
s->nc = nc;
topic_expr[0].qos = MG_MQTT_QOS(0);
asprintf((char **)&topic_expr[0].topic, "xterminal/%s/%s/srvdata", devid, id);
mg_mqtt_subscribe(nc, topic_expr, 1, 44);
printf("sub:%s\n", topic_expr[0].topic);
free((char *)topic_expr[0].topic);
snprintf(s->topic_dev, sizeof(s->topic_dev), "xterminal/%s/%s/devdata", devid, id);
ev_io_init(&s->watcher, pty_read_cb, pty, EV_READ);
s->watcher.data = s;
ev_io_start(EV_DEFAULT, &s->watcher);
}
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data)
{
if (ev == MG_EV_CONNECT) {
/* Connect to mqtt broker */
struct mg_send_mqtt_handshake_opts opts;
memset(&opts, 0, sizeof(opts));
mg_set_protocol_mqtt(nc);
mg_send_mqtt_handshake_opt(nc, devid, opts);
} else if (ev == MG_EV_MQTT_CONNACK) {
struct mg_mqtt_message *msg = (struct mg_mqtt_message *)ev_data;
struct mg_mqtt_topic_expression topic_expr[1];
if (msg->connack_ret_code != MG_EV_MQTT_CONNACK_ACCEPTED) {
printf("Got mqtt connection error: %d\n", msg->connack_ret_code);
ev_break(EV_DEFAULT, EVBREAK_ALL);
return;
}
topic_expr[0].qos = MG_MQTT_QOS(0);
asprintf((char **)&topic_expr[0].topic, "xterminal/%s/connect/+", devid);
mg_mqtt_subscribe(nc, topic_expr, 1, 0);
free((char *)topic_expr[0].topic);
} else if (ev == MG_EV_MQTT_PUBLISH) {
struct mg_mqtt_message *msg = (struct mg_mqtt_message *)ev_data;
if (memmem(msg->topic.p, msg->topic.len, "connect", strlen("connect"))) {
char id[33] = "";
strncpy(id, msg->topic.p + 31, 32);
new_connect(nc, id);
} else {
char id[33] = "";
struct session *s = NULL;
strncpy(id, msg->topic.p + 23, 32);
s = find_session_by_id(id);
if (s) {
int ret = write(s->pty, msg->payload.p, msg->payload.len);
if (ret < 0)
perror("write");
}
}
} else if (ev == MG_EV_CLOSE) {
printf("connection close:%p\n", nc);
}
}
static void signal_cb(struct ev_loop *loop, ev_signal *w, int revents)
{
if (w->signum == SIGINT) {
ev_break(loop, EVBREAK_ALL);
}
}
static void heartbeat_cb(struct ev_loop *loop, ev_timer *w, int revents)
{
struct mg_connection *nc = (struct mg_connection *)w->data;
mg_mqtt_publish(nc, "xterminal/heartbeat", 0, MG_MQTT_QOS(0), devid, strlen(devid));
}
static int get_iface_mac(const char *ifname, char mac[6])
{
int r, s;
struct ifreq ifr;
strncpy(ifr.ifr_name, ifname, 15);
ifr.ifr_name[15] = '\0';
s = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == s) {
perror("socket");
return -1;
}
r = ioctl(s, SIOCGIFHWADDR, &ifr);
if (r == -1) {
perror("ioctl");
close(s);
return -1;
}
close(s);
memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
return 0;
}
int main(int argc, char *argv[])
{
struct ev_loop *loop = EV_DEFAULT;
ev_signal sigint_watcher;
ev_timer heartbeat_timer;
struct mg_mgr mgr;
struct mg_connection *nc;
char mac[6] = "";
const char *s_address = "localhost:1883";
mg_mgr_init(&mgr, NULL);
nc = mg_connect(&mgr, s_address, ev_handler);
if (!nc) {
fprintf(stderr, "mg_connect(%s) failed\n", s_address);
exit(1);
}
ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
sigint_watcher.data = nc;
ev_signal_start(loop, &sigint_watcher);
ev_timer_init(&heartbeat_timer, heartbeat_cb, 0.1, 2.0);
heartbeat_timer.data = nc;
ev_timer_start(loop, &heartbeat_timer);
get_iface_mac("enp3s0", mac);
devid = calloc(1, 13);
sprintf(devid, "%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
printf("devid:%s\n", devid);
ev_run(loop, 0);
printf("exit...\n");
free(devid);
mg_mgr_free(&mgr);
return 0;
}
+83
View File
@@ -0,0 +1,83 @@
#!/usr/bin/lua
local ev = require("ev")
local evmg = require("evmongoose")
local posix = require 'posix'
local cjson = require("cjson")
local loop = ev.Loop.default
local mgr = evmg.init()
local devid = "448A5BEC4927"
local session = {}
local function new_connect(nc, id)
local pid, pty = evmg.forkpty()
if pid == 0 then
posix.exec ("/bin/login")
end
session[id] = {
pid = pid,
pty = pty
}
mgr:mqtt_subscribe(nc, "xterminal/" .. devid .. "/" .. id .. "/srvdata");
local topic_dev = "xterminal/" .. devid .. "/" .. id .. "/devdata"
ev.IO.new(function(loop, w, revents)
local d, err = posix.read(w:getfd(), 1024)
if not d then
w:stop(loop)
error("read error:" .. err)
end
mgr:mqtt_publish(nc, topic_dev, d);
end, pty, ev.READ):start(loop)
print("new connect ok")
end
local function ev_handle(nc, event, msg)
if event == evmg.MG_EV_CONNECT then
mgr:set_protocol_mqtt(nc)
mgr:send_mqtt_handshake_opt(nc)
elseif event == evmg.MG_EV_MQTT_CONNACK then
if msg.connack_ret_code ~= evmg.MG_EV_MQTT_CONNACK_ACCEPTED then
print("Got mqtt connection error:", msg.connack_ret_code)
return
end
mgr:mqtt_subscribe(nc, "xterminal/" .. devid .. "/connect/+");
ev.Timer.new(function(loop, timer, revents)
mgr:mqtt_publish(nc, "xterminal/heartbeat", devid)
end, 0.1, 3):start(loop)
elseif event == evmg.MG_EV_MQTT_PUBLISH then
local topic = msg.topic
print("mqtt recv:", topic)
if topic:match("connect") then
local id = topic:match("xterminal/" .. devid .. "/connect/(%w+)")
new_connect(nc, id)
else
local id = topic:match("xterminal/" .. devid .. "/(%w+)/srvdata")
posix.write(session[id].pty, msg.payload);
end
end
end
mgr:connect("localhost:1883", ev_handle)
ev.Signal.new(function(loop, sig, revents)
loop:unloop()
end, ev.SIGINT):start(loop)
print("start...")
loop:loop()
mgr:destroy()
print("exit...")