surenyi
9 years ago
44 changed files with 1475 additions and 1340 deletions
@ -1,10 +0,0 @@ |
|||
#ifndef __ALARM_PROVIDER_H__ |
|||
#define __ALARM_PROVIDER_H__ |
|||
|
|||
class AlarmProvider { |
|||
public: |
|||
void onAlarm(const char *str, int len); |
|||
}; |
|||
|
|||
#endif |
|||
|
@ -1,170 +0,0 @@ |
|||
#include <errno.h> |
|||
#include <string.h> |
|||
#include <time.h> |
|||
#include "UdpEvent.h" |
|||
#include "Log.h" |
|||
#include "Wan.h" |
|||
#include "Lan.h" |
|||
#include "IdMapper.h" |
|||
#include "AudioBridge.h" |
|||
|
|||
class AudioUpEvent : public UdpEvent { |
|||
private: |
|||
AudioBridge *_bge; |
|||
public: |
|||
AudioUpEvent(Udp u, AudioBridge *_b) : UdpEvent(u), _bge(_b){} |
|||
void onEvent(int /* fd */, short what) |
|||
{ |
|||
uint8_t buf[1500] = {0}; |
|||
|
|||
/* send to uplink */ |
|||
if (what & UDP_READ) { |
|||
int n = _udp.recv(buf, sizeof buf); |
|||
if (n > 0) |
|||
_bge->onUpComplete(buf, n); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
class AudioDownEvent : public UdpEvent { |
|||
private: |
|||
AudioBridge *_bge; |
|||
public: |
|||
AudioDownEvent(Udp u, AudioBridge *_b) : UdpEvent(u), _bge(_b){} |
|||
void onEvent(int /* fd */, short what) |
|||
{ |
|||
if (what & UDP_READ) { |
|||
uint8_t buf[700] = {0}; |
|||
int n = _udp.recv(buf, sizeof buf); |
|||
if (n > 0) |
|||
_bge->onDownComplete(buf, n); |
|||
} |
|||
/* send to downlink */ |
|||
} |
|||
}; |
|||
|
|||
AudioBridge::AudioBridge() |
|||
:_uplink(0), _downlink(0), _downProvider(0), _upProvider(0), _audioEncType(AUDIO_ENC_ALL) |
|||
{ |
|||
_encSeq = 0; |
|||
_decSeq = 0; |
|||
} |
|||
|
|||
uint8_t AudioBridge::getCheckNum(uint8_t *buf, int len) |
|||
{ |
|||
uint32_t sum = 0; |
|||
|
|||
for (int i = 0; i < len; ++i) { |
|||
sum += buf[i]; |
|||
} |
|||
|
|||
return (sum & 0xff); |
|||
} |
|||
|
|||
void AudioBridge::onUpAudio(struct MsgAudio *audio) |
|||
{ |
|||
memset(&_encBuf, 0, sizeof _encBuf); |
|||
|
|||
_encBuf.id1 = 0xAC; |
|||
_encBuf.id2 = 0x93; |
|||
_encBuf.id3 = 0x27; |
|||
_encBuf.id4 = 0x21; |
|||
_encBuf.swId = 0xB1; |
|||
_encBuf.fromId = 0xD8; |
|||
_encBuf.toId = 0xFF; |
|||
_encBuf.toSwId = 0xE2; |
|||
_encBuf.origPosId = IdMapper::getMappedWanId(audio->sender); |
|||
_encBuf.encType = _audioEncType; |
|||
_encBuf.contentId = 0xED; |
|||
_encBuf.flyType = 0; |
|||
_encBuf.flyId = 0; |
|||
|
|||
/* XXX: here need to convert */ |
|||
size_t len = audio->payloadLen; |
|||
if (len > sizeof _encBuf.payload) |
|||
len = sizeof _encBuf.payload; |
|||
memcpy(_encBuf.payload, audio->payload, len); |
|||
|
|||
_encBuf.timeStamp = htonl(time(NULL)); |
|||
_encBuf.seqNum = htonl(++_encSeq); |
|||
_encBuf.checkNum = getCheckNum((uint8_t *)&_encBuf, sizeof _encBuf - 2); |
|||
_encBuf.id5 = 0x14; |
|||
|
|||
_uplink->getUdp().send(&_encBuf, sizeof _encBuf); |
|||
} |
|||
|
|||
void AudioBridge::onDownAudio(struct WanAudioType *wat) |
|||
{ |
|||
memset(&_decBuf, 0, sizeof _decBuf); |
|||
|
|||
_decBuf.id1 = 0xAC; |
|||
_decBuf.id2 = 0x93; |
|||
_decBuf.id3 = 0x27; |
|||
_decBuf.id4 = 0x21; |
|||
_decBuf.swId = 0xB1; |
|||
_decBuf.origSwId = 0xD8; |
|||
_decBuf.toId = 0xFF; |
|||
_decBuf.toSwId = 0xE2; |
|||
_decBuf.origPosId = 0xB1; |
|||
_decBuf.encType = _audioEncType; |
|||
_decBuf.contentId = 0xED; |
|||
_decBuf.flyType = wat->apType; |
|||
_decBuf.flyId = wat->apId; |
|||
|
|||
memcpy(_decBuf.payload, wat->mgrAudio, 6); |
|||
memcpy(_decBuf.auxPayload, wat->auxAudio, 6); |
|||
_decBuf.timeStamp = htonl(time(NULL)); |
|||
_decBuf.seqNum = htonl(++_decSeq); |
|||
_decBuf.checkNum = getCheckNum((uint8_t *)&_decBuf, sizeof _decBuf - 2); |
|||
_decBuf.id5 = 0x14; |
|||
_downlink->getUdp().send((uint8_t *)&_decBuf, sizeof _decBuf); |
|||
} |
|||
|
|||
int AudioBridge::__makeLink(Udp & _u, const char *bridge_ip, int bridge_port, const char *local_ip, int local_port) |
|||
{ |
|||
if (_u.open() < 0) { |
|||
Log.printf("'%s[%d]: can't create socket\n", __FILE__, __LINE__); |
|||
return -1; |
|||
} |
|||
if (_u.bind(local_ip, local_port) < 0) { |
|||
Log.printf("'%s[%d]: can't bind [%s:%d] socket (%d: %s)\n", __FILE__, __LINE__, local_ip, local_port, errno, strerror(errno)); |
|||
_u.close(); |
|||
return -2; |
|||
} |
|||
if (_u.connect(bridge_ip, bridge_port) < 0) { |
|||
Log.printf("'%s[%d]: can't connect [%s:%d] socket\n", __FILE__, __LINE__, local_ip, local_port); |
|||
_u.close(); |
|||
return -3; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
int AudioBridge::begin(const char *bridge_ip, int bridge_port, const char *local_ip, int down_port, int up_port) |
|||
{ |
|||
Udp d, u; |
|||
|
|||
if (__makeLink(d, bridge_ip, bridge_port, local_ip, down_port) < 0) { |
|||
return -1; |
|||
} |
|||
|
|||
if (__makeLink(u, bridge_ip, bridge_port, local_ip, up_port) < 0) { |
|||
d.close(); |
|||
return -2; |
|||
} |
|||
_downlink = new AudioDownEvent(d, this); |
|||
_uplink = new AudioUpEvent(u, this); |
|||
return 0; |
|||
} |
|||
|
|||
void AudioBridge::onUpComplete(uint8_t *data, int len) |
|||
{ |
|||
if (_upProvider) |
|||
_upProvider->onComplete(data, len); |
|||
} |
|||
|
|||
void AudioBridge::onDownComplete(uint8_t *data, int len) |
|||
{ |
|||
if (_downProvider) |
|||
_downProvider->onComplete(data, len); |
|||
} |
|||
|
@ -1,95 +0,0 @@ |
|||
#ifndef __AUDIO_BRIDGE_H__ |
|||
#define __AUDIO_BRIDGE_H__ |
|||
|
|||
#include <stdint.h> |
|||
|
|||
#include "AudioProvider.h" |
|||
#include "UdpReadable.h" |
|||
|
|||
#define AUDIO_ENC_ALL 0x00 |
|||
#define AUDIO_ENC_10 0x01 |
|||
#define AUDIO_ENC_712 0x02 |
|||
|
|||
#define AUDIO_ENC_PKT_LEN (666) |
|||
#define AUDIO_DEC_PKT_LEN (64) |
|||
|
|||
struct AudioEncType { |
|||
uint8_t id1; |
|||
uint8_t id2; |
|||
uint8_t id3; |
|||
uint8_t id4; |
|||
uint16_t resv0; |
|||
uint8_t swId; |
|||
uint8_t fromId; |
|||
uint8_t toId; |
|||
uint8_t toSwId; |
|||
uint8_t origPosId; |
|||
uint8_t resv1; |
|||
uint8_t encType; |
|||
uint8_t contentId; |
|||
uint8_t flyType; |
|||
uint8_t flyId; |
|||
uint8_t payload[640]; |
|||
uint32_t timeStamp; |
|||
uint32_t seqNum; |
|||
uint8_t checkNum; |
|||
uint8_t id5; |
|||
} __attribute__((packed)); |
|||
|
|||
struct AudioDecInType { |
|||
uint8_t id1; |
|||
uint8_t id2; |
|||
uint8_t id3; |
|||
uint8_t id4; |
|||
uint16_t resv0; |
|||
uint8_t swId; |
|||
uint8_t origSwId; |
|||
uint8_t toId; |
|||
uint8_t toSwId; |
|||
uint8_t origPosId; |
|||
uint8_t resv1; |
|||
uint8_t encType; |
|||
uint8_t contentId; |
|||
uint8_t flyType; |
|||
uint8_t flyId; |
|||
uint8_t payload[6]; |
|||
uint8_t auxPayload[6]; |
|||
uint8_t resv2[26]; |
|||
uint32_t timeStamp; |
|||
uint32_t seqNum; |
|||
uint8_t checkNum; |
|||
uint8_t id5; |
|||
} __attribute((packed)); |
|||
|
|||
class UdpEvent; |
|||
class Udp; |
|||
class AudioBridge : public AudioUpProvider, public AudioDownProvider { |
|||
private: |
|||
UdpEvent *_uplink; |
|||
UdpEvent *_downlink; |
|||
AudioCompleteProvider *_downProvider; |
|||
AudioCompleteProvider *_upProvider; |
|||
uint8_t _audioEncType; |
|||
AudioEncType _encBuf; |
|||
uint32_t _encSeq; |
|||
AudioDecInType _decBuf; |
|||
uint32_t _decSeq; |
|||
int __makeLink(Udp & _u, const char *brige_ip, int bridge_port, const char *local_ip, int local_port); |
|||
uint8_t getCheckNum(uint8_t *buf, int len); |
|||
public: |
|||
AudioBridge(); |
|||
virtual void onUpAudio(struct MsgAudio *); |
|||
virtual void onDownAudio(struct WanAudioType *); |
|||
|
|||
int begin(const char *bridge_ip, int bridge_port, const char *local_ip, int down_port, int up_port); |
|||
|
|||
void setAudioEncType(uint8_t type) { _audioEncType = type;} |
|||
void setUpCompleteProvider(AudioCompleteProvider *_p) {_upProvider = _p;} |
|||
void setDownCompleteProvider(AudioCompleteProvider *_p) {_downProvider = _p;} |
|||
|
|||
void onDownComplete(uint8_t *data, int len); |
|||
void onUpComplete(uint8_t *data, int len); |
|||
}; |
|||
|
|||
#endif |
|||
|
@ -1,23 +0,0 @@ |
|||
#ifndef __AUDIO__PROVIDER_H__ |
|||
#define __AUDIO__PROVIDER_H__ |
|||
|
|||
struct MsgAudio; |
|||
struct WanAudioType; |
|||
|
|||
class AudioUpProvider { |
|||
public: |
|||
virtual void onUpAudio(MsgAudio * audio) = 0; |
|||
}; |
|||
|
|||
class AudioDownProvider { |
|||
public: |
|||
virtual void onDownAudio(struct WanAudioType *) = 0; |
|||
}; |
|||
|
|||
class AudioCompleteProvider { |
|||
public: |
|||
virtual void onComplete(uint8_t *buf, int len) = 0; |
|||
}; |
|||
|
|||
#endif |
|||
|
@ -1,17 +0,0 @@ |
|||
#ifndef __CRC32_H__ |
|||
#define __CRC32_H__ |
|||
|
|||
#include <stdint.h> |
|||
|
|||
class Crc32 { |
|||
private: |
|||
unsigned int crc_table[256]; |
|||
void init(); |
|||
uint32_t doCrc(uint32_t crc,unsigned char *buffer, unsigned int size); |
|||
public: |
|||
Crc32(); |
|||
uint32_t crc(uint8_t *data, int len); |
|||
}; |
|||
|
|||
#endif |
|||
|
@ -1,85 +0,0 @@ |
|||
#include <errno.h> |
|||
#include <string.h> |
|||
#include "CharConv.h" |
|||
#include "UdpEvent.h" |
|||
#include "Runtime.h" |
|||
#include "Lan.h" |
|||
#include "Log.h" |
|||
|
|||
#define LOIFADDR "127.0.0.1" |
|||
|
|||
void CharConv::isReadable(Udp &u) |
|||
{ |
|||
uint8_t buf[1560] = {0}; |
|||
int len; |
|||
|
|||
Log.printf("char readable\n"); |
|||
if ((len = u.recv(buf, sizeof buf)) <= 0) |
|||
return; |
|||
Log.printf("char conv recv: %d bytes\n", len); |
|||
/* XXX : packetizing ... */ |
|||
Runtime.getLan().send(buf, len); |
|||
} |
|||
|
|||
int CharConv::begin(int to_port, int from_port) |
|||
{ |
|||
Udp u; |
|||
|
|||
if (u.open() < 0) { |
|||
Log.printf("'%s[%d]: can't create socket\n", __FILE__, __LINE__); |
|||
return -1; |
|||
} |
|||
|
|||
if (u.bind(LOIFADDR, from_port) < 0) { |
|||
Log.printf("'%s[%d]: can't bind [%s:%d] socket (%d: %s)\n", __FILE__, __LINE__, LOIFADDR, from_port, errno, strerror(errno)); |
|||
u.close(); |
|||
return -2; |
|||
} |
|||
if (u.connect(LOIFADDR, to_port) < 0) { |
|||
Log.printf("'%s[%d]: can't connect [%s:%d] socket\n", __FILE__, __LINE__, LOIFADDR, to_port); |
|||
u.close(); |
|||
return -3; |
|||
} |
|||
|
|||
UdpReadable::begin(u); |
|||
_cd = iconv_open("GB2312", "UTF-8"); |
|||
if (_cd == (iconv_t)-1) { |
|||
Log.printf("can't crate iconv conventer\n"); |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
void CharConv::onAlarm(const char *str, int len) |
|||
{ |
|||
uint8_t buf[1500] = {0}; |
|||
int idx = 0; |
|||
|
|||
Log.printf("alarm: %d, %s\n", len, str); |
|||
|
|||
buf[idx++] = 0x68; |
|||
buf[idx++] = 0x00; |
|||
buf[idx++] = 0x00; |
|||
buf[idx++] = 0x80; |
|||
buf[idx++] = len & 0xff; |
|||
buf[idx++] = (len >> 8) & 0xff; |
|||
memcpy(buf + idx, str, len); |
|||
idx += len; |
|||
uint32_t cs = _crc.crc((uint8_t *)str, len); |
|||
buf[idx++] = cs & 0xff; |
|||
buf[idx++] = (cs >> 8) & 0xff; |
|||
buf[idx++] = (cs >> 16) & 0xff; |
|||
buf[idx++] = (cs >> 24) & 0xff; |
|||
|
|||
int n = _udp.send(buf, idx); |
|||
Log.printf("conv sending: %d bytes\n", n); |
|||
} |
|||
|
|||
void CharConv::end() |
|||
{ |
|||
if (_cd != (iconv_t)-1) { |
|||
iconv_close(_cd); |
|||
_cd = (iconv_t)-1; |
|||
} |
|||
_udp.close(); |
|||
} |
|||
|
@ -1,24 +0,0 @@ |
|||
#ifndef __CHAR_CONV_H__ |
|||
#define __CHAR_CONV_H__ |
|||
|
|||
#include <iconv.h> |
|||
#include "AlarmProvider.h" |
|||
#include "UdpReadable.h" |
|||
#include "CRC32.h" |
|||
|
|||
class CharConv : public AlarmProvider, public UdpReadable { |
|||
private: |
|||
Crc32 _crc; |
|||
iconv_t _cd; |
|||
public: |
|||
int begin(int to_port, int from_port); |
|||
void onAlarm(const char *str, int len); |
|||
virtual void isReadable(Udp &u); |
|||
void end(); |
|||
~CharConv() { |
|||
end(); |
|||
} |
|||
}; |
|||
|
|||
#endif |
|||
|
@ -1,200 +0,0 @@ |
|||
#include <unistd.h> |
|||
#include <string.h> |
|||
#include "IdMapper.h" |
|||
#include "UdpEvent.h" |
|||
#include "AudioBridge.h" |
|||
#include "Lan.h" |
|||
#include "Log.h" |
|||
|
|||
#define LAN_PKT_MIN_LEN (16) |
|||
#define LAN_PKT_MAX_LEN (256) |
|||
|
|||
int Lan::begin(const char *group_addr, int port, const char *local_if) |
|||
{ |
|||
Udp udp; |
|||
|
|||
#if 0 |
|||
Log.printf("struct MsgCmd: %d\n", sizeof (struct MsgCmd)); |
|||
Log.printf("struct MsgTermStatus: %d\n", sizeof (struct MsgTermStatus)); |
|||
Log.printf("struct MsgAudio: %d\n", sizeof (struct MsgAudio)); |
|||
Log.printf("struct MsgAlarm: %d\n", sizeof (struct MsgAlarm)); |
|||
#endif |
|||
|
|||
if (udp.open() < 0) { |
|||
Log.printf("'%s[%d]: can't create Lan socket\n", __func__, __LINE__); |
|||
return -1; |
|||
} |
|||
Log.printf("local: %s, %s, %d\n", local_if, group_addr, port); |
|||
if (udp.bind(local_if, port) < 0) { |
|||
Log.printf("'%s[%d]: can't bind Lan socket\n", __func__, __LINE__); |
|||
udp.close(); |
|||
return -2; |
|||
} |
|||
|
|||
if (udp.connect(group_addr, port) < 0) { |
|||
Log.printf("'%s[%d]: can't connect Lan socket\n", __func__, __LINE__); |
|||
udp.close(); |
|||
return -3; |
|||
} |
|||
|
|||
UdpReadable::begin(udp); |
|||
_myseq = 0; |
|||
return 0; |
|||
} |
|||
|
|||
void Lan::doCmd(uint8_t *buf, int len) |
|||
{ |
|||
struct MsgCmd hdr, *sdp; |
|||
struct MsgTermStatus *mts; |
|||
uint8_t out; |
|||
uint16_t cmd; |
|||
|
|||
sdp = (struct MsgCmd *)(buf); |
|||
hdr = *sdp; |
|||
cmd = ntohs(hdr.msgCmd); |
|||
// Log.printf("Lan cmd [%02x]\n", cmd);
|
|||
switch (cmd) { |
|||
case MSG_CMD_HANDSHAKE: |
|||
hdr.sender = sdp->recver; |
|||
hdr.recver = sdp->sender; |
|||
hdr.msgCmd = htons(MSG_RES_HANDSHAKE); |
|||
#if 0 |
|||
do { |
|||
uint8_t *dp; |
|||
dp = (uint8_t *)&hdr; |
|||
for (int x= 0; x < 12; ++x) { |
|||
Log.printf("%02x ", dp[x]); |
|||
} |
|||
Log.printf("\n"); |
|||
} while (0); |
|||
#endif |
|||
send(&hdr, sizeof hdr); |
|||
len -= sizeof hdr; |
|||
buf += sizeof hdr; |
|||
/* 6 x 4 bytes:
|
|||
* 0 1 2 3 |
|||
* id downlink ptt alarm |
|||
*/ |
|||
while (len > (int)sizeof (*mts)) { |
|||
mts = (struct MsgTermStatus *)buf; |
|||
out = IdMapper::getMappedWanId(mts->termId); |
|||
if (out > 0) { |
|||
_provider->onStatus(out, mts->isAlarm); |
|||
} |
|||
len -= sizeof (*mts); |
|||
buf += sizeof (*mts); |
|||
} |
|||
break; |
|||
case MSG_CMD_PTTON: |
|||
out = IdMapper::getMappedWanId(hdr.sender); |
|||
if (out > 0) { |
|||
_provider->onPTT(this, &hdr, out, true); |
|||
} |
|||
break; |
|||
case MSG_CMD_PTTOFF: |
|||
out = IdMapper::getMappedWanId(hdr.sender); |
|||
if (out > 0) { |
|||
_provider->onPTT(this, &hdr, out, false); |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
|
|||
|
|||
void Lan::doAudio(uint8_t *buf, int len) |
|||
{ |
|||
struct MsgAudio *laph; |
|||
|
|||
if (len < (int)(sizeof *laph)) |
|||
return; |
|||
|
|||
laph = (struct MsgAudio *)(buf); |
|||
laph->payloadLen = ntohl(laph->payloadLen); |
|||
if (len < (int)(sizeof *laph + laph->payloadLen)) { |
|||
Log.printf("audio length too small, total: %d, payload: %d\n", len, laph->payloadLen); |
|||
return; |
|||
} |
|||
|
|||
Log.printf("recver< %d >: %x, sender: %x, mode: %d, recvChannel: %d, sendChannel: %d\n", |
|||
laph->payloadLen, laph->recver, laph->sender, laph->mode, laph->recvChannel, laph->sendChannel); |
|||
_audioUp->onUpAudio(laph); |
|||
} |
|||
|
|||
void Lan::isReadable(Udp & _u) |
|||
{ |
|||
uint8_t buf[LAN_PKT_MAX_LEN] = {0}; |
|||
int len; |
|||
|
|||
if ((len = _u.recv(buf, sizeof buf)) < LAN_PKT_MIN_LEN) |
|||
return; |
|||
#if 0 |
|||
do { |
|||
Log.printf("Lan: %d bytes\n", len); |
|||
for (int x = 0; x < len; ++x) { |
|||
Log.printf("%02x%c", buf[x], ((x + 1) % 16) ? ' ' : '\n'); |
|||
} |
|||
Log.printf("\n"); |
|||
} while (0); |
|||
#endif |
|||
switch (buf[0]) { |
|||
case MSG_TYPE_CMD: |
|||
doCmd(buf, len); |
|||
break; |
|||
case MSG_TYPE_AUDIO: |
|||
doAudio(buf, len); |
|||
break; |
|||
case MSG_TYPE_ALARM: |
|||
break; |
|||
} |
|||
} |
|||
|
|||
void Lan::onComplete(uint8_t *buf, int len) |
|||
{ |
|||
struct AudioEncType *aet; |
|||
struct MsgAudio *ma; |
|||
uint8_t msg[MSG_AUDIO_LEN] = {0}; |
|||
|
|||
if (len < (int)(sizeof *aet)) { |
|||
Log.printf("Audio too short.\n"); |
|||
return; |
|||
} |
|||
|
|||
ma = (struct MsgAudio *)(msg); |
|||
aet = (struct AudioEncType *)(buf); |
|||
ma->type = MSG_TYPE_AUDIO; |
|||
ma->recver = 0x19; |
|||
ma->sender = 0x07; |
|||
ma->swid = 0xB1; |
|||
ma->seqNum = htonl(++_myseq); |
|||
ma->payloadLen = 160; |
|||
|
|||
/*XXX: transcode aet->payload */ |
|||
memcpy(ma->payload, aet->payload, ma->payloadLen); |
|||
|
|||
send(msg, sizeof msg); |
|||
} |
|||
|
|||
int Lan::onResponse(int resp_type, struct MsgCmd *hdr, int status) |
|||
{ |
|||
struct MsgCmd pkt; |
|||
|
|||
pkt = *hdr; |
|||
pkt.recver = hdr->sender; |
|||
pkt.sender = hdr->recver; |
|||
switch (resp_type) { |
|||
case RESP_PTT_ON: |
|||
if (status == RESP_PTT_OK) { |
|||
pkt.msgCmd = htons(MSG_RES_PTTON); |
|||
} else { |
|||
pkt.msgCmd = htons(MSG_REFUSE_PTTON); |
|||
} |
|||
break; |
|||
case RESP_PTT_OFF: |
|||
pkt.msgCmd = htons(MSG_RES_PTTOFF); |
|||
break; |
|||
} |
|||
send(&pkt, sizeof pkt); |
|||
|
|||
return 0; |
|||
} |
|||
|
@ -1,15 +0,0 @@ |
|||
#ifndef __PTTPROVIDER_H__ |
|||
#define __PTTPROVIDER_H__ |
|||
|
|||
#include <stdint.h> |
|||
|
|||
class Lan; |
|||
struct MsgCmd; |
|||
class PTTProvider { |
|||
public: |
|||
virtual void onPTT(Lan *, struct MsgCmd *hdr, uint8_t posId, bool on) = 0; |
|||
virtual void onStatus(uint8_t id, uint8_t status) = 0; |
|||
}; |
|||
|
|||
#endif |
|||
|
@ -1,186 +0,0 @@ |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <getopt.h> |
|||
#include "Runtime.h" |
|||
#include "Log.h" |
|||
#include "Udp.h" |
|||
#include "Timer.h" |
|||
|
|||
#define LAN_IF "eth0" |
|||
#define LAN_FROM "192.168.9.25" |
|||
#define LAN_PORT 5600 |
|||
|
|||
#define BGE_IP "192.168.9.19" |
|||
#define BGE_PORT 6419 |
|||
#define BGE_UP_PORT 6402 |
|||
#define BGE_DOWN_PORT 6400 |
|||
|
|||
/*
|
|||
* Please disable rp_filter |
|||
* edit /etc/sysctl.conf |
|||
* |
|||
* net.ipv4.conf.default.rp_filter = 0 |
|||
* net.ipv4.conf.all.rp_filter = 0 |
|||
* |
|||
* add route for eth1 |
|||
* route add -net 192.168.31.0/24 dev eth1 |
|||
*/ |
|||
#if 1 |
|||
#define WAN_IF "eth1" |
|||
#define WAN_GROUP "225.0.0.5" |
|||
#define WAN_GROUP_PORT 8300 |
|||
#define WAN_STATUS_PORT 8100 |
|||
#else |
|||
#define WAN_IF "eth0" |
|||
#define WAN_GROUP "224.0.0.24" |
|||
#define WAN_GROUP_PORT 8300 |
|||
#define WAN_STATUS_PORT 5100 |
|||
#endif |
|||
|
|||
Runtime::Runtime() |
|||
{ |
|||
struct event_config *config; |
|||
|
|||
_lan_if = (char *)LAN_IF; |
|||
_lan_grp_addr = (char *)LAN_FROM; |
|||
_lan_grp_port = LAN_PORT; |
|||
|
|||
_bge_ip = (char *)BGE_IP; |
|||
_bge_port = BGE_PORT; |
|||
_up_port = BGE_UP_PORT; |
|||
_down_port = BGE_DOWN_PORT; |
|||
|
|||
_wan_if = (char *)WAN_IF; |
|||
_wan_grp_addr = (char *)WAN_GROUP; |
|||
_wan_grp_port = WAN_GROUP_PORT; |
|||
_wan_status_port = WAN_STATUS_PORT; |
|||
|
|||
config = event_config_new(); |
|||
event_config_avoid_method(config, "select"); |
|||
event_config_require_features(config, EV_FEATURE_ET); |
|||
_evbase = event_base_new_with_config(config); |
|||
event_config_free(config); |
|||
} |
|||
|
|||
int Runtime::loop() |
|||
{ |
|||
return event_base_dispatch(_evbase); |
|||
} |
|||
|
|||
void Runtime::printHelp() |
|||
{ |
|||
fprintf(stderr, "usage: cmd [option], options as:\n\t" |
|||
"--lanif, -l: set lan ethx interface, eg: \"ethx\"\n\t" |
|||
"--landest, -g: set lan multicast address, eg: \"192.168.9.25\"\n\t" |
|||
"--lanport, -p: set lan multicast port, eg: 5600\n\t" |
|||
"--wanif, -w: set lan ethx interface, eg: \"ethx\"\n\t" |
|||
"--wangrp, -r: set lan multicast address, eg: \"255.0.0.5\"\n\t" |
|||
"--wanport, -t: set lan multicast port, eg: 5600\n\t" |
|||
"--help, -h: print this message.\n"); |
|||
} |
|||
|
|||
void Runtime::parseArgs(int argc, char *argv[]) |
|||
{ |
|||
int c; |
|||
static struct option options[] = { |
|||
{"lanif", required_argument, NULL, 'l'}, |
|||
{"landest", required_argument, NULL, 'g'}, |
|||
{"lanport", required_argument, NULL, 'p'}, |
|||
{"wanif", required_argument, NULL, 'w'}, |
|||
{"wangrp", required_argument, NULL, 'r'}, |
|||
{"wanport", required_argument, NULL, 't'}, |
|||
{"wanstport", required_argument, NULL, 'o'}, |
|||
{"help", no_argument, NULL, 'h'}, |
|||
{NULL, 0, NULL, 0} |
|||
}; |
|||
|
|||
while ((c = getopt_long(argc, argv, "l:g:p:w:r:t:o:h", options, NULL)) != -1) { |
|||
switch (c) { |
|||
case 'l': |
|||
_lan_if = optarg; |
|||
break; |
|||
case 'g': |
|||
_lan_grp_addr = optarg; |
|||
break; |
|||
case 'p': |
|||
_lan_grp_port = atoi(optarg); |
|||
break; |
|||
case 'w': |
|||
_wan_if = optarg; |
|||
break; |
|||
case 'r': |
|||
_wan_grp_addr = optarg; |
|||
case 't': |
|||
_wan_grp_port = atoi(optarg); |
|||
break; |
|||
case 'o': |
|||
_wan_status_port = atoi(optarg); |
|||
break; |
|||
case 'h': |
|||
printHelp(); |
|||
exit(0); |
|||
} |
|||
} |
|||
} |
|||
|
|||
class AlarmTimer : public Timer { |
|||
private: |
|||
CharConv *_c; |
|||
int count; |
|||
public: |
|||
AlarmTimer(CharConv *c) : _c(c), count(0){} |
|||
virtual void onTimer() |
|||
{ |
|||
char buf[128]; |
|||
snprintf(buf, sizeof buf, "数量这么多数据还是不错"); |
|||
_c->onAlarm(buf, strlen(buf)); |
|||
} |
|||
}; |
|||
|
|||
void Runtime::begin() |
|||
{ |
|||
char local_if[64] = {0}; |
|||
char wan_if[64] = {0}; |
|||
|
|||
Log.begin(); |
|||
|
|||
Udp::getip(_lan_if, local_if, sizeof local_if); |
|||
if (_lan.begin(_lan_grp_addr, _lan_grp_port, local_if) < 0) { |
|||
Log.printf("lan initialize failed.\n"); |
|||
exit(-1); |
|||
} |
|||
|
|||
if (_abge.begin(_bge_ip, _bge_port, local_if, _down_port, _up_port) < 0) { |
|||
Log.printf("audio bridge initialize failed.\n"); |
|||
exit(-2); |
|||
} |
|||
|
|||
Udp::getip(_wan_if, wan_if, sizeof wan_if); |
|||
if (_wan.begin(_wan_grp_addr, _wan_grp_port, wan_if, _wan_status_port) < 0) { |
|||
Log.printf("wan initialize failed.\n"); |
|||
exit(-3); |
|||
} |
|||
|
|||
if (_conv.begin(6801, 6802) < 0) { |
|||
Log.printf("char convter initiazlie failed.\n"); |
|||
exit(-4); |
|||
} |
|||
|
|||
#if 1 |
|||
static AlarmTimer at(&_conv); |
|||
at.begin(); |
|||
at.active(1000); |
|||
#endif |
|||
_abge.setDownCompleteProvider(&_lan); |
|||
_abge.setUpCompleteProvider(&_wan); |
|||
|
|||
_lan.setAudioUpProvider(&_abge); |
|||
_wan.setAudioDownProvider(&_abge); |
|||
|
|||
_lan.setPTTProvider(&_wan); |
|||
|
|||
_wan.setAlarmProvider(&_conv); |
|||
} |
|||
|
|||
class Runtime Runtime; |
|||
|
@ -1,52 +0,0 @@ |
|||
#ifndef __RUNTIME_H____ |
|||
#define __RUNTIME_H____ |
|||
|
|||
#include <event2/event.h> |
|||
#include "Lan.h" |
|||
#include "Wan.h" |
|||
#include "AudioBridge.h" |
|||
#include "CharConv.h" |
|||
|
|||
class Runtime { |
|||
private: |
|||
struct event_base *_evbase; |
|||
|
|||
/* lan config */ |
|||
Lan _lan; |
|||
char *_lan_if; |
|||
char *_lan_grp_addr; |
|||
int _lan_grp_port; |
|||
|
|||
/* audio bridge */ |
|||
AudioBridge _abge; |
|||
char *_bge_ip; |
|||
int _bge_port; |
|||
int _up_port; |
|||
int _down_port; |
|||
|
|||
/* Wan */ |
|||
Wan _wan; |
|||
char *_wan_if; |
|||
char *_wan_grp_addr; |
|||
int _wan_grp_port; |
|||
int _wan_status_port; |
|||
|
|||
CharConv _conv; |
|||
|
|||
void printHelp(); |
|||
public: |
|||
Runtime(); |
|||
|
|||
void parseArgs(int argc, char *argv[]); |
|||
|
|||
void begin(); |
|||
|
|||
Lan & getLan() { return _lan;} |
|||
|
|||
struct event_base *getEvBase() const { return _evbase;} |
|||
int loop(); |
|||
}; |
|||
|
|||
extern class Runtime Runtime; |
|||
#endif |
|||
|
@ -1,35 +0,0 @@ |
|||
#include "Timer.h" |
|||
#include "Log.h" |
|||
#include "Runtime.h" |
|||
|
|||
void Timer::__helper(int , short, void *arg) |
|||
{ |
|||
Timer *t = static_cast<Timer *>(arg); |
|||
t->onTimer(); |
|||
} |
|||
|
|||
void Timer::onTimer() |
|||
{ |
|||
Log.printf("dummy timer\n"); |
|||
} |
|||
|
|||
void Timer::begin() |
|||
{ |
|||
event_assign(&_evt, Runtime.getEvBase(), -1, EV_TIMEOUT | EV_PERSIST, __helper, this); |
|||
} |
|||
|
|||
void Timer::active(int ms) |
|||
{ |
|||
struct timeval tv; |
|||
|
|||
tv.tv_sec = ms / 1000; |
|||
tv.tv_usec = ms % 1000; |
|||
|
|||
event_add(&_evt, &tv); |
|||
} |
|||
|
|||
void Timer::deactive() |
|||
{ |
|||
event_del(&_evt); |
|||
} |
|||
|
@ -1,18 +0,0 @@ |
|||
#ifndef __ETIMER_H__ |
|||
#define __ETIMER_H__ |
|||
|
|||
#include <event2/event.h> |
|||
#include <event2/event_struct.h> |
|||
class Timer { |
|||
private: |
|||
struct event _evt; |
|||
static void __helper(int fd, short what, void *arg); |
|||
public: |
|||
void begin(); |
|||
void active(int us); |
|||
void deactive(); |
|||
virtual void onTimer(); |
|||
}; |
|||
|
|||
#endif |
|||
|
@ -1,28 +0,0 @@ |
|||
#ifndef __UDP_H___ |
|||
#define __UDP_H___ |
|||
|
|||
#include <netinet/in.h> |
|||
#include <netinet/in.h> |
|||
#include <net/if.h> |
|||
#include <arpa/inet.h> |
|||
|
|||
class Udp { |
|||
protected: |
|||
int sock; |
|||
struct sockaddr_in destAddr; |
|||
bool isMcast; |
|||
public: |
|||
Udp(); |
|||
Udp(const Udp &_u) { sock = _u.sock;} |
|||
int getFd() { return sock;} |
|||
int open(); |
|||
int send(const void *buf, int len); |
|||
int recv(void *buf, int len); |
|||
int openMulticast(const char *group, int port, const char *local); |
|||
int bind(const char *ip_dot, int port); |
|||
int connect(const char *to, int to_port); |
|||
int close(); |
|||
static int getip(const char *ethx, char *ip_dot, int len); |
|||
}; |
|||
#endif |
|||
|
@ -1,41 +0,0 @@ |
|||
#include "Udp.h" |
|||
#include "UdpEvent.h" |
|||
#include "Log.h" |
|||
#include "Runtime.h" |
|||
|
|||
UdpEvent::~UdpEvent() |
|||
{ |
|||
if (_evt) { |
|||
end(); |
|||
} |
|||
_udp.close(); |
|||
} |
|||
|
|||
void UdpEvent::__helper(int fd, short what, void *arg) |
|||
{ |
|||
UdpEvent *ue = static_cast<UdpEvent*>(arg); |
|||
|
|||
ue->onEvent(fd, what); |
|||
} |
|||
|
|||
void UdpEvent::end() |
|||
{ |
|||
event_del(_evt); |
|||
event_free(_evt); |
|||
_evt = NULL; |
|||
} |
|||
|
|||
int UdpEvent::begin(int flag, bool oneshot) |
|||
{ |
|||
if (!oneshot) |
|||
flag |= EV_PERSIST; |
|||
|
|||
Log.printf("flag: %02x, fd: %d\n", flag, _udp.getFd()); |
|||
_evt = event_new(Runtime.getEvBase(), _udp.getFd(), flag, __helper, this); |
|||
if (_evt) { |
|||
event_add(_evt, NULL); |
|||
return 0; |
|||
} |
|||
return -1; |
|||
} |
|||
|
@ -1,33 +0,0 @@ |
|||
#ifndef __UDPEVENT_H__ |
|||
#define __UDPEVENT_H__ |
|||
|
|||
#include <event2/event.h> |
|||
|
|||
#include "Udp.h" |
|||
|
|||
class UdpEvent { |
|||
protected: |
|||
Udp _udp; |
|||
struct event *_evt; |
|||
private: |
|||
static void __helper(int fd, short what, void *arg); |
|||
public: |
|||
enum {UDP_READ = EV_READ, UDP_WRITE = EV_WRITE}; |
|||
|
|||
UdpEvent() : _evt(0){} |
|||
UdpEvent(Udp _u) : _udp(_u), _evt(0) {} |
|||
|
|||
int begin(Udp udp, int type, bool onshot = false); |
|||
|
|||
int begin(int type, bool oneshot = false); |
|||
void end(); |
|||
|
|||
Udp & getUdp(){return _udp;} |
|||
|
|||
virtual void onEvent(int , short) = 0; |
|||
|
|||
virtual ~UdpEvent(); |
|||
}; |
|||
|
|||
#endif |
|||
|
@ -1,26 +0,0 @@ |
|||
#include "Udp.h" |
|||
#include "UdpReadable.h" |
|||
#include "Log.h" |
|||
#include "Runtime.h" |
|||
|
|||
void UdpReadable::__helper(int /* fd */, short what, void *arg) |
|||
{ |
|||
UdpReadable *p = static_cast<UdpReadable *>(arg); |
|||
if (what & EV_READ) { |
|||
p->isReadable(p->_udp); |
|||
} |
|||
} |
|||
|
|||
int UdpReadable::begin(const Udp &udp) |
|||
{ |
|||
_udp = udp; |
|||
event_assign(&_evt, Runtime.getEvBase(), _udp.getFd(), EV_READ | EV_PERSIST, __helper, this); |
|||
event_add(&_evt, NULL); |
|||
return 0; |
|||
} |
|||
|
|||
void UdpReadable::end() |
|||
{ |
|||
event_del(&_evt); |
|||
} |
|||
|
@ -1,23 +0,0 @@ |
|||
#ifndef __UDPREDABLE_H__ |
|||
#define __UDPREDABLE_H__ |
|||
|
|||
#include <event2/event.h> |
|||
#include <event2/event_struct.h> |
|||
|
|||
#include "Udp.h" |
|||
|
|||
class UdpReadable { |
|||
protected: |
|||
Udp _udp; |
|||
private: |
|||
struct event _evt; |
|||
static void __helper(int fd, short what, void *arg); |
|||
public: |
|||
int begin(const Udp &udp); |
|||
void end(); |
|||
virtual void isReadable(Udp &) = 0; |
|||
virtual ~UdpReadable() {end();} |
|||
}; |
|||
|
|||
#endif |
|||
|
@ -1,112 +0,0 @@ |
|||
#include <time.h> |
|||
#include <errno.h> |
|||
#include <string.h> |
|||
#include "UdpEvent.h" |
|||
#include "Wan.h" |
|||
#include "Lan.h" |
|||
#include "Log.h" |
|||
|
|||
int Wan::begin(const char *group_addr, int port, const char *wlan_if, int stport) |
|||
{ |
|||
Udp udp; |
|||
|
|||
Log.printf("Wan group: %s, port: %d, wan: %s\n", group_addr, port, wlan_if); |
|||
if (udp.openMulticast(group_addr, port, wlan_if) < 0) { |
|||
Log.printf("'%s[%d]: can't create multicast socket\n", __FILE__, __LINE__); |
|||
return -1; |
|||
} |
|||
|
|||
if (_stSock.openMulticast(group_addr, stport, wlan_if) < 0) { |
|||
Log.printf("'%s[%d]: can't create status multicast socket\n", __FILE__, __LINE__); |
|||
udp.close(); |
|||
return -2; |
|||
} |
|||
UdpReadable::begin(udp); |
|||
|
|||
_stSeq = 0; |
|||
memset(&_stBuf, 0, sizeof _stBuf); |
|||
_stBuf.id1 = 0xAC; |
|||
_stBuf.id2 = 0x93; |
|||
_stBuf.id3 = 0x27; |
|||
_stBuf.id4 = 0x21; |
|||
_stBuf.srcPosId = 0xB1; |
|||
_stBuf.srcSwId = 0xD8; |
|||
_stBuf.destSwId = 0xE8; |
|||
_stBuf.initPosId = 0xB1; |
|||
_stBuf.contentId = 0xF3; |
|||
_stBuf.id5 = 0x14; |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
void Wan::isReadable(Udp &u) |
|||
{ |
|||
uint8_t data[1500] = {0}; |
|||
int len; |
|||
|
|||
if ((len = u.recv(data, sizeof data)) <= 0) |
|||
return; |
|||
|
|||
#if 0 |
|||
Log.printf("Wan recv: %d bytes\n", len); |
|||
for (int i = 0; i < len; ++i) { |
|||
Log.printf("%02x%c", data[i], ((i + 1) % 16) ? ' ' : '\n'); |
|||
} |
|||
Log.printf("\n"); |
|||
#endif |
|||
|
|||
if ((data[0] == 0xAA) && (data[1] == 0x55)) { |
|||
if ((len == 32) && (data[6] == 0x91)) { |
|||
struct WanAudioType *wat = (struct WanAudioType *)data; |
|||
_audioDown->onDownAudio(wat); |
|||
} |
|||
} |
|||
/*XXX: if alarming , call _alarm->onAlarm() */ |
|||
if ((data[0] == 0xAC) && (data[1] == 0x93)) { |
|||
if ((len == 64) && (data[13] == 0xF0)) { |
|||
} |
|||
} |
|||
} |
|||
|
|||
void Wan::onPTT(Lan *ln, struct MsgCmd *hdr, uint8_t posId, bool on) |
|||
{ |
|||
if (on) { |
|||
} else { |
|||
} |
|||
ln->onResponse(on ? Lan::RESP_PTT_ON : Lan::RESP_PTT_OFF, hdr, RESP_PTT_OK); |
|||
} |
|||
|
|||
void Wan::onComplete(uint8_t *buf, int len) |
|||
{ |
|||
_udp.send(buf, len); |
|||
} |
|||
|
|||
void Wan::onStatus(uint8_t id, uint8_t status) |
|||
{ |
|||
int len = 0; |
|||
uint8_t *sbuf; |
|||
|
|||
_stBuf.destId = status ? id : 0; |
|||
/*
|
|||
* 0: don't start |
|||
* 1: playing |
|||
* 2: idle |
|||
*/ |
|||
_stBuf.status = status ? 0x01 : 0x02; |
|||
_stBuf.time = htonl(time(NULL)); |
|||
_stBuf.seq = htonl(++_stSeq); |
|||
uint32_t cs = 0; |
|||
len = sizeof _stBuf - 2; |
|||
sbuf = (uint8_t *)&_stBuf; |
|||
for (int x = 0; x < len; ++x) { |
|||
cs += sbuf[x]; |
|||
} |
|||
_stBuf.checkNum = cs & 0xff; |
|||
|
|||
len = _stSock.send(&_stBuf, sizeof _stBuf); |
|||
if (len < 0) { |
|||
Log.printf("%s:%d errno (%d) %s\n", __FILE__, __LINE__, errno, strerror(errno)); |
|||
} |
|||
// Log.printf("status sending %d bytes\n", len);
|
|||
} |
|||
|
@ -0,0 +1,124 @@ |
|||
#include <errno.h> |
|||
#include <string.h> |
|||
#include <iconv.h> |
|||
#include "runtime.h" |
|||
#include "udp_readable.h" |
|||
#include "char_conv.h" |
|||
#include "log.h" |
|||
#include "crc.h" |
|||
|
|||
struct alarm_handler { |
|||
struct wan_alarm_handler base; |
|||
char_conv_t *thiz; |
|||
}; |
|||
|
|||
struct char_conv { |
|||
struct udp_readable base; |
|||
struct alarm_handler alarm; |
|||
iconv_t cd; |
|||
}; |
|||
|
|||
#define LOIFADDR "127.0.0.1" |
|||
|
|||
struct wan_alarm_handler *char_conv_get_alarm_handler(char_conv_t *cv) |
|||
{ |
|||
return &cv->alarm.base; |
|||
} |
|||
|
|||
static void __is_readable(udp_readable_t *ur) |
|||
{ |
|||
uint8_t buf[1560] = {0}; |
|||
int len; |
|||
char_conv_t *cv; |
|||
|
|||
cv = (char_conv_t *)ur; |
|||
log_printf("char readable\n"); |
|||
if ((len = ur->udp->recv(ur->udp, buf, sizeof buf)) <= 0) |
|||
return; |
|||
log_printf("char conv recv: %d bytes\n", len); |
|||
/* XXX : packetizing ... */ |
|||
// Runtime.getLan().send(buf, len);
|
|||
} |
|||
|
|||
static void __on_alarm(struct wan_alarm_handler *self, struct WanAlarmType *wat) |
|||
{ |
|||
uint8_t buf[1500] = {0}; |
|||
int idx = 0; |
|||
size_t len; |
|||
unsigned int cs; |
|||
struct alarm_handler *ah = (struct alarm_handler *)self; |
|||
char_conv_t *cv = ah->thiz; |
|||
|
|||
buf[idx++] = 0x68; |
|||
buf[idx++] = 0x00; |
|||
buf[idx++] = 0x00; |
|||
buf[idx++] = 0x80; |
|||
|
|||
for (len = 0; len < sizeof wat->msg; ++len) { |
|||
if (wat->msg[len] == 0) { |
|||
break; |
|||
} |
|||
} |
|||
|
|||
buf[idx++] = len & 0xff; |
|||
buf[idx++] = (len >> 8) & 0xff; |
|||
memcpy(buf + idx, wat->msg, len); |
|||
|
|||
idx += len; |
|||
|
|||
cs = crc(wat->msg, len); |
|||
|
|||
buf[idx++] = cs & 0xff; |
|||
buf[idx++] = (cs >> 8) & 0xff; |
|||
buf[idx++] = (cs >> 16) & 0xff; |
|||
buf[idx++] = (cs >> 24) & 0xff; |
|||
|
|||
do { |
|||
udp_t *_udp = cv->base.udp; |
|||
int n = _udp->send(_udp, buf, idx); |
|||
log_printf("conv sending: %d bytes\n", n); |
|||
} while (0); |
|||
} |
|||
|
|||
char_conv_t *char_conv_new(int to_port, int from_port) |
|||
{ |
|||
udp_t *u; |
|||
char_conv_t *cv; |
|||
|
|||
if ((u = udp_open()) == NULL) { |
|||
log_printf("'%s[%d]: can't create socket\n", __FILE__, __LINE__); |
|||
return NULL; |
|||
} |
|||
|
|||
if (u->bind(u, LOIFADDR, from_port) < 0) { |
|||
log_printf("'%s[%d]: can't bind [%s:%d] socket (%d: %s)\n", __FILE__, __LINE__, LOIFADDR, from_port, errno, strerror(errno)); |
|||
u->close(u); |
|||
return NULL; |
|||
} |
|||
if (u->connect(u, LOIFADDR, to_port) < 0) { |
|||
log_printf("'%s[%d]: can't connect [%s:%d] socket\n", __FILE__, __LINE__, LOIFADDR, to_port); |
|||
u->close(u); |
|||
return NULL; |
|||
} |
|||
|
|||
cv = (char_conv_t *)udp_readable_open(sizeof *cv, u); |
|||
cv->base.is_readable = __is_readable; |
|||
|
|||
cv->cd = iconv_open("GB2312", "UTF-8"); |
|||
if (cv->cd == (iconv_t)-1) { |
|||
log_printf("can't crate iconv conventer\n"); |
|||
udp_readable_close(&cv->base); |
|||
return NULL; |
|||
} |
|||
cv->alarm.base.on_alarm = __on_alarm; |
|||
cv->alarm.thiz = cv; |
|||
|
|||
return cv; |
|||
} |
|||
|
|||
void char_conv_free(char_conv_t *cv) |
|||
{ |
|||
iconv_close(cv->cd); |
|||
udp_readable_close(&cv->base); |
|||
} |
|||
|
@ -0,0 +1,11 @@ |
|||
#ifndef __CHAR_CONV_H__ |
|||
#define __CHAR_CONV_H__ |
|||
|
|||
#include "wan.h" |
|||
typedef struct char_conv char_conv_t; |
|||
|
|||
char_conv_t *char_conv_new(int to_port, int from_port); |
|||
struct wan_alarm_handler *char_conv_get_alarm_handler(char_conv_t *cv); |
|||
void char_conv_free(char_conv_t *cv); |
|||
#endif |
|||
|
@ -0,0 +1,237 @@ |
|||
#include <stdlib.h> |
|||
#include <errno.h> |
|||
#include <string.h> |
|||
#include <time.h> |
|||
#include <stdint.h> |
|||
#include "codec.h" |
|||
#include "log.h" |
|||
#include "lan.h" |
|||
#include "wan.h" |
|||
#include "udp_readable.h" |
|||
#include "IdMapper.h" |
|||
|
|||
struct uplink_audio_handler { |
|||
struct lan_audio_handler base; |
|||
codec_t *thiz; |
|||
}; |
|||
|
|||
struct downlink_audio_handler { |
|||
struct wan_audio_handler base; |
|||
codec_t *thiz; |
|||
}; |
|||
|
|||
struct udp_wrapper { |
|||
struct udp_readable base; |
|||
codec_t *thiz; |
|||
}; |
|||
|
|||
struct codec { |
|||
struct uplink_audio_handler _audio_up; |
|||
struct downlink_audio_handler _audio_down; |
|||
struct udp_wrapper *_uplink; |
|||
struct udp_wrapper *_downlink; |
|||
|
|||
struct codec_complete *_up_complete; |
|||
struct codec_complete *_down_complete; |
|||
|
|||
uint8_t _audioEncType; |
|||
struct AudioEncType _encBuf; |
|||
uint32_t _encSeq; |
|||
struct AudioDecInType _decBuf; |
|||
uint32_t _decSeq; |
|||
}; |
|||
|
|||
struct lan_audio_handler *codec_get_uplink_handler(codec_t *cc) |
|||
{ |
|||
return &cc->_audio_up.base; |
|||
} |
|||
|
|||
struct wan_audio_handler *codec_get_downlink_handler(codec_t *cc) |
|||
{ |
|||
return &cc->_audio_down.base; |
|||
} |
|||
|
|||
void codec_set_enc_type(codec_t *cc, int type) |
|||
{ |
|||
cc->_audioEncType = type; |
|||
} |
|||
|
|||
void codec_set_up_complete(codec_t *cc, struct codec_complete *ccp) |
|||
{ |
|||
cc->_up_complete = ccp; |
|||
} |
|||
|
|||
void codec_set_down_complete(codec_t *cc, struct codec_complete *ccp) |
|||
{ |
|||
cc->_down_complete = ccp; |
|||
} |
|||
|
|||
static uint8_t getcs(uint8_t *buf, int len) |
|||
{ |
|||
uint32_t sum = 0; |
|||
|
|||
for (int i = 0; i < len; ++i) { |
|||
sum += buf[i]; |
|||
} |
|||
|
|||
return (sum & 0xff); |
|||
} |
|||
|
|||
static void __on_up_audio( struct lan_audio_handler *lh, |
|||
struct MsgAudio *audio) |
|||
{ |
|||
struct uplink_audio_handler *uh = (struct uplink_audio_handler *)lh; |
|||
codec_t *cc = uh->thiz; |
|||
struct udp_wrapper *uw = cc->_uplink; |
|||
udp_t *u = uw->base.udp; |
|||
|
|||
memset(&cc->_encBuf, 0, sizeof cc->_encBuf); |
|||
|
|||
cc->_encBuf.id1 = 0xAC; |
|||
cc->_encBuf.id2 = 0x93; |
|||
cc->_encBuf.id3 = 0x27; |
|||
cc->_encBuf.id4 = 0x21; |
|||
cc->_encBuf.swId = 0xB1; |
|||
cc->_encBuf.fromId = 0xD8; |
|||
cc->_encBuf.toId = 0xFF; |
|||
cc->_encBuf.toSwId = 0xE2; |
|||
cc->_encBuf.origPosId = getMappedWanId(audio->sender); |
|||
cc->_encBuf.encType = cc->_audioEncType; |
|||
cc->_encBuf.contentId = 0xED; |
|||
cc->_encBuf.flyType = 0; |
|||
cc->_encBuf.flyId = 0; |
|||
|
|||
/* XXX: here need to convert */ |
|||
size_t len = audio->payloadLen; |
|||
if (len > sizeof cc->_encBuf.payload) |
|||
len = sizeof cc->_encBuf.payload; |
|||
memcpy(cc->_encBuf.payload, audio->payload, len); |
|||
|
|||
cc->_encBuf.timeStamp = htonl(time(NULL)); |
|||
cc->_encBuf.seqNum = htonl(++cc->_encSeq); |
|||
cc->_encBuf.checkNum = getcs((uint8_t *)&cc->_encBuf, sizeof cc->_encBuf - 2); |
|||
cc->_encBuf.id5 = 0x14; |
|||
|
|||
u->send(u, &cc->_encBuf, sizeof cc->_encBuf); |
|||
} |
|||
|
|||
static void __on_down_audio(struct wan_audio_handler *wh, struct WanAudioType *wat) |
|||
{ |
|||
struct downlink_audio_handler *dh = (struct downlink_audio_handler *)wh; |
|||
codec_t *cc = dh->thiz; |
|||
struct udp_wrapper *uw = cc->_downlink; |
|||
udp_t *u = uw->base.udp; |
|||
|
|||
memset(&cc->_decBuf, 0, sizeof cc->_decBuf); |
|||
|
|||
cc->_decBuf.id1 = 0xAC; |
|||
cc->_decBuf.id2 = 0x93; |
|||
cc->_decBuf.id3 = 0x27; |
|||
cc->_decBuf.id4 = 0x21; |
|||
cc->_decBuf.swId = 0xB1; |
|||
cc->_decBuf.origSwId = 0xD8; |
|||
cc->_decBuf.toId = 0xFF; |
|||
cc->_decBuf.toSwId = 0xE2; |
|||
cc->_decBuf.origPosId = 0xB1; |
|||
cc->_decBuf.encType = cc->_audioEncType; |
|||
cc->_decBuf.contentId = 0xED; |
|||
cc->_decBuf.flyType = wat->apType; |
|||
cc->_decBuf.flyId = wat->apId; |
|||
|
|||
memcpy(cc->_decBuf.payload, wat->mgrAudio, 6); |
|||
memcpy(cc->_decBuf.auxPayload, wat->auxAudio, 6); |
|||
cc->_decBuf.timeStamp = htonl(time(NULL)); |
|||
cc->_decBuf.seqNum = htonl(++cc->_decSeq); |
|||
cc->_decBuf.checkNum = getcs((uint8_t *)&cc->_decBuf, sizeof cc->_decBuf - 2); |
|||
cc->_decBuf.id5 = 0x14; |
|||
u->send(u, (uint8_t *)&cc->_decBuf, sizeof cc->_decBuf); |
|||
} |
|||
|
|||
static udp_t *__make_link(const char *bridge_ip, int bridge_port, const char *local_ip, int local_port) |
|||
{ |
|||
udp_t *_u; |
|||
if ((_u = udp_open()) == NULL) { |
|||
log_printf("'%s[%d]: can't create socket\n", __FILE__, __LINE__); |
|||
return NULL; |
|||
} |
|||
if (_u->bind(_u, local_ip, local_port) < 0) { |
|||
log_printf("'%s[%d]: can't bind [%s:%d] socket (%d: %s)\n", __FILE__, __LINE__, local_ip, local_port, errno, strerror(errno)); |
|||
_u->close(_u); |
|||
return NULL; |
|||
} |
|||
if (_u->connect(_u, bridge_ip, bridge_port) < 0) { |
|||
log_printf("'%s[%d]: can't connect [%s:%d] socket\n", __FILE__, __LINE__, local_ip, local_port); |
|||
_u->close(_u); |
|||
return NULL; |
|||
} |
|||
return _u; |
|||
} |
|||
|
|||
static void __up_readable(udp_readable_t *ur) |
|||
{ |
|||
int n; |
|||
uint8_t buf[1500] = {0}; |
|||
struct udp_wrapper *uw = (struct udp_wrapper *)ur; |
|||
codec_t *cc = uw->thiz; |
|||
udp_t *u = ur->udp; |
|||
struct codec_complete *ccp = cc->_up_complete; |
|||
|
|||
/* send to uplink */ |
|||
if ((n = u->recv(u, buf, sizeof buf)) > 0) { |
|||
ccp->on_complete(ccp, buf, n); |
|||
} |
|||
} |
|||
|
|||
static void __down_readable(udp_readable_t *ur) |
|||
{ |
|||
int n; |
|||
uint8_t buf[1500] = {0}; |
|||
struct udp_wrapper *uw = (struct udp_wrapper *)ur; |
|||
codec_t *cc = uw->thiz; |
|||
udp_t *u = ur->udp; |
|||
struct codec_complete *ccp = cc->_down_complete; |
|||
|
|||
/* send to uplink */ |
|||
if ((n = u->recv(u, buf, sizeof buf)) > 0) { |
|||
ccp->on_complete(ccp, buf, n); |
|||
} |
|||
} |
|||
|
|||
codec_t *codec_new(const char *bridge_ip, int bridge_port, const char *local_ip, int down_port, int up_port) |
|||
{ |
|||
codec_t *cc; |
|||
udp_t *d, *u; |
|||
|
|||
if ((d = __make_link(bridge_ip, bridge_port, local_ip, down_port)) == NULL) { |
|||
return NULL; |
|||
} |
|||
|
|||
if (( u = __make_link( bridge_ip, bridge_port, local_ip, up_port)) == NULL) { |
|||
d->close(d); |
|||
return NULL; |
|||
} |
|||
cc = calloc(1, sizeof *cc); |
|||
cc->_downlink = (struct udp_wrapper *)udp_readable_open(sizeof *cc->_downlink, d); |
|||
cc->_downlink->base.is_readable = __down_readable; |
|||
cc->_downlink->thiz = cc; |
|||
cc->_uplink = (struct udp_wrapper *)udp_readable_open(sizeof *cc->_uplink, u); |
|||
cc->_uplink->base.is_readable = __up_readable; |
|||
cc->_uplink->thiz = cc; |
|||
cc->_audio_up.thiz = cc; |
|||
cc->_audio_up.base.on_audio = __on_up_audio; |
|||
cc->_audio_down.thiz = cc; |
|||
cc->_audio_down.base.on_audio = __on_down_audio; |
|||
|
|||
return cc; |
|||
} |
|||
|
|||
void codec_free(codec_t *cc) |
|||
{ |
|||
struct udp_wrapper *uw; |
|||
uw = cc->_downlink; |
|||
udp_readable_close(&uw->base); |
|||
uw = cc->_uplink; |
|||
udp_readable_close(&uw->base); |
|||
free(cc); |
|||
} |
|||
|
@ -0,0 +1,77 @@ |
|||
#ifndef __AUDIO_CODEC_H__ |
|||
#define __AUDIO_CODEC_H__ |
|||
|
|||
#include <stdint.h> |
|||
#include "lan.h" |
|||
#include "wan.h" |
|||
|
|||
#define AUDIO_ENC_ALL 0x00 |
|||
#define AUDIO_ENC_10 0x01 |
|||
#define AUDIO_ENC_712 0x02 |
|||
|
|||
#define AUDIO_ENC_PKT_LEN (666) |
|||
#define AUDIO_DEC_PKT_LEN (64) |
|||
|
|||
struct AudioEncType { |
|||
uint8_t id1; |
|||
uint8_t id2; |
|||
uint8_t id3; |
|||
uint8_t id4; |
|||
uint16_t resv0; |
|||
uint8_t swId; |
|||
uint8_t fromId; |
|||
uint8_t toId; |
|||
uint8_t toSwId; |
|||
uint8_t origPosId; |
|||
uint8_t resv1; |
|||
uint8_t encType; |
|||
uint8_t contentId; |
|||
uint8_t flyType; |
|||
uint8_t flyId; |
|||
uint8_t payload[640]; |
|||
uint32_t timeStamp; |
|||
uint32_t seqNum; |
|||
uint8_t checkNum; |
|||
uint8_t id5; |
|||
} __attribute__((packed)); |
|||
|
|||
struct AudioDecInType { |
|||
uint8_t id1; |
|||
uint8_t id2; |
|||
uint8_t id3; |
|||
uint8_t id4; |
|||
uint16_t resv0; |
|||
uint8_t swId; |
|||
uint8_t origSwId; |
|||
uint8_t toId; |
|||
uint8_t toSwId; |
|||
uint8_t origPosId; |
|||
uint8_t resv1; |
|||
uint8_t encType; |
|||
uint8_t contentId; |
|||
uint8_t flyType; |
|||
uint8_t flyId; |
|||
uint8_t payload[6]; |
|||
uint8_t auxPayload[6]; |
|||
uint8_t resv2[26]; |
|||
uint32_t timeStamp; |
|||
uint32_t seqNum; |
|||
uint8_t checkNum; |
|||
uint8_t id5; |
|||
} __attribute((packed)); |
|||
|
|||
struct codec_complete { |
|||
void (*on_complete)(struct codec_complete *, uint8_t *buf, int len); |
|||
}; |
|||
|
|||
typedef struct codec codec_t; |
|||
codec_t *codec_new(const char *bridge_ip, int bridge_port, const char *local_ip, int down_port, int up_port); |
|||
void codec_set_up_complete(codec_t *cc, struct codec_complete *ccp); |
|||
void codec_set_enc_type(codec_t *cc, int type); |
|||
void codec_set_down_complete(codec_t *cc, struct codec_complete *ccp); |
|||
struct lan_audio_handler *codec_get_uplink_handler(codec_t *cc); |
|||
struct wan_audio_handler *codec_get_downlink_handler(codec_t *cc); |
|||
void codec_free(codec_t *cc); |
|||
|
|||
#endif |
|||
|
@ -0,0 +1,7 @@ |
|||
#ifndef __CRC_H__ |
|||
#define __CRC_H__ |
|||
|
|||
void crc_begin(void); |
|||
unsigned int crc(void *buf, int len); |
|||
#endif |
|||
|
@ -0,0 +1,239 @@ |
|||
#include <unistd.h> |
|||
#include <string.h> |
|||
#include <stdlib.h> |
|||
#include <stdbool.h> |
|||
#include "IdMapper.h" |
|||
#include "udp_readable.h" |
|||
#include "log.h" |
|||
#include "lan.h" |
|||
#include "codec.h" |
|||
|
|||
#define LAN_PKT_MIN_LEN (16) |
|||
#define LAN_PKT_MAX_LEN (256) |
|||
|
|||
struct decode_handler { |
|||
struct codec_complete base; |
|||
lan_t *thiz; |
|||
}; |
|||
|
|||
struct lan { |
|||
struct udp_readable base; |
|||
uint32_t seqnum; |
|||
struct decode_handler dec; |
|||
struct lanmsg_handler *_provider; |
|||
struct lan_audio_handler *_uplink; |
|||
}; |
|||
|
|||
struct codec_complete *lan_get_decode_handler(lan_t *ln) |
|||
{ |
|||
return &ln->dec.base; |
|||
} |
|||
|
|||
void lan_set_msghandler(lan_t *ln, struct lanmsg_handler *h) |
|||
{ |
|||
ln->_provider = h; |
|||
} |
|||
|
|||
void lan_set_uplink_handler(lan_t *ln, struct lan_audio_handler *h) |
|||
{ |
|||
ln->_uplink = h; |
|||
} |
|||
|
|||
static void __on_downlink(struct codec_complete *cc, uint8_t *buf, int len) |
|||
{ |
|||
struct AudioEncType *aet; |
|||
struct MsgAudio *ma; |
|||
uint8_t msg[MSG_AUDIO_LEN] = {0}; |
|||
struct decode_handler *dh = (struct decode_handler *)cc; |
|||
udp_t *u = dh->thiz->base.udp; |
|||
|
|||
if (len < (int)(sizeof *aet)) { |
|||
log_printf("Audio too short.\n"); |
|||
return; |
|||
} |
|||
|
|||
ma = (struct MsgAudio *)(msg); |
|||
aet = (struct AudioEncType *)(buf); |
|||
ma->type = MSG_TYPE_AUDIO; |
|||
ma->recver = 0x19; |
|||
ma->sender = 0x07; |
|||
ma->swid = 0xB1; |
|||
ma->seqNum = htonl(++dh->thiz->seqnum); |
|||
ma->payloadLen = 160; |
|||
|
|||
/*XXX: transcode aet->payload */ |
|||
memcpy(ma->payload, aet->payload, ma->payloadLen); |
|||
|
|||
u->send(u, msg, sizeof msg); |
|||
} |
|||
static void __do_audio(lan_t *ln, uint8_t *buf, int len) |
|||
{ |
|||
struct MsgAudio *laph; |
|||
|
|||
if (len < (int)(sizeof *laph)) |
|||
return; |
|||
|
|||
laph = (struct MsgAudio *)(buf); |
|||
laph->payloadLen = ntohl(laph->payloadLen); |
|||
if (len < (int)(sizeof *laph + laph->payloadLen)) { |
|||
log_printf("audio length too small, total: %d, payload: %d\n", len, laph->payloadLen); |
|||
return; |
|||
} |
|||
|
|||
log_printf("recver< %d >: %x, sender: %x, mode: %d, recvChannel: %d, sendChannel: %d\n", |
|||
laph->payloadLen, laph->recver, laph->sender, laph->mode, laph->recvChannel, laph->sendChannel); |
|||
ln->_uplink->on_audio(ln->_uplink, laph); |
|||
} |
|||
|
|||
static void __do_cmd(lan_t *ln, udp_t *u, uint8_t *buf, int len) |
|||
{ |
|||
struct MsgCmd hdr, *sdp; |
|||
struct MsgTermStatus *mts; |
|||
uint8_t out; |
|||
uint16_t cmd; |
|||
|
|||
sdp = (struct MsgCmd *)(buf); |
|||
hdr = *sdp; |
|||
cmd = ntohs(hdr.msgCmd); |
|||
log_printf("Lan cmd [%02x]\n", cmd); |
|||
switch (cmd) { |
|||
case MSG_CMD_HANDSHAKE: |
|||
hdr.sender = sdp->recver; |
|||
hdr.recver = sdp->sender; |
|||
hdr.msgCmd = htons(MSG_RES_HANDSHAKE); |
|||
#if 1 |
|||
do { |
|||
uint8_t *dp; |
|||
dp = (uint8_t *)&hdr; |
|||
for (int x= 0; x < 12; ++x) { |
|||
log_printf("%02x ", dp[x]); |
|||
} |
|||
log_printf("\n"); |
|||
} while (0); |
|||
#endif |
|||
u->send(u, &hdr, sizeof hdr); |
|||
len -= sizeof hdr; |
|||
buf += sizeof hdr; |
|||
/* 6 x 4 bytes:
|
|||
* 0 1 2 3 |
|||
* id downlink ptt alarm |
|||
*/ |
|||
while (len > (int)sizeof (*mts)) { |
|||
mts = (struct MsgTermStatus *)buf; |
|||
out = getMappedWanId(mts->termId); |
|||
if (out > 0) { |
|||
ln->_provider->on_status(ln->_provider, out, mts->isAlarm); |
|||
} |
|||
len -= sizeof (*mts); |
|||
buf += sizeof (*mts); |
|||
} |
|||
break; |
|||
case MSG_CMD_PTTON: |
|||
out = getMappedWanId(hdr.sender); |
|||
if (out > 0) { |
|||
ln->_provider->on_ptt(ln->_provider, ln, &hdr, out, true); |
|||
} |
|||
break; |
|||
case MSG_CMD_PTTOFF: |
|||
out = getMappedWanId(hdr.sender); |
|||
if (out > 0) { |
|||
ln->_provider->on_ptt(ln->_provider, ln, &hdr, out, false); |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
|
|||
static void __is_readable(udp_readable_t *ur) |
|||
{ |
|||
uint8_t buf[LAN_PKT_MAX_LEN] = {0}; |
|||
int len; |
|||
udp_t *_u = ur->udp; |
|||
|
|||
log_printf("lan reading\n"); |
|||
if ((len = _u->recv(_u, buf, sizeof buf)) < LAN_PKT_MIN_LEN) { |
|||
return; |
|||
} |
|||
#if 1 |
|||
do { |
|||
log_printf("Lan: %d bytes\n", len); |
|||
for (int x = 0; x < len; ++x) { |
|||
log_printf("%02x%c", buf[x], ((x + 1) % 16) ? ' ' : '\n'); |
|||
} |
|||
log_printf("\n"); |
|||
} while (0); |
|||
#endif |
|||
switch (buf[0]) { |
|||
case MSG_TYPE_CMD: |
|||
__do_cmd((lan_t *)(ur), _u, buf, len); |
|||
break; |
|||
case MSG_TYPE_AUDIO: |
|||
__do_audio((lan_t *)ur, buf, len); |
|||
break; |
|||
case MSG_TYPE_ALARM: |
|||
break; |
|||
} |
|||
} |
|||
|
|||
int lan_ptt_response(lan_t *ln, int resp_type, struct MsgCmd *hdr, int status) |
|||
{ |
|||
struct MsgCmd pkt; |
|||
udp_t *u = ln->base.udp; |
|||
|
|||
pkt = *hdr; |
|||
pkt.recver = hdr->sender; |
|||
pkt.sender = hdr->recver; |
|||
switch (resp_type) { |
|||
case RESP_PTT_ON: |
|||
if (status == RESP_PTT_OK) { |
|||
pkt.msgCmd = htons(MSG_RES_PTTON); |
|||
} else { |
|||
pkt.msgCmd = htons(MSG_REFUSE_PTTON); |
|||
} |
|||
break; |
|||
case RESP_PTT_OFF: |
|||
pkt.msgCmd = htons(MSG_RES_PTTOFF); |
|||
break; |
|||
} |
|||
u->send(u, &pkt, sizeof pkt); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
lan_t *lan_new(const char *dest_addr, int port, const char *local_if) |
|||
{ |
|||
udp_t *u; |
|||
lan_t *ln; |
|||
|
|||
if ((u = udp_open()) == NULL) { |
|||
log_printf("'%s[%d]: can't create Lan socket\n", __func__, __LINE__); |
|||
return NULL; |
|||
} |
|||
log_printf("local: %s, %s, %d\n", local_if, dest_addr, port); |
|||
if (u->bind(u, local_if, port) < 0) { |
|||
log_printf("'%s[%d]: can't bind Lan socket\n", __func__, __LINE__); |
|||
u->close(u); |
|||
return NULL; |
|||
} |
|||
|
|||
if (u->connect(u, dest_addr, port) < 0) { |
|||
log_printf("'%s[%d]: can't connect Lan socket\n", __func__, __LINE__); |
|||
u->close(u); |
|||
return NULL; |
|||
} |
|||
ln = (lan_t *)udp_readable_open(sizeof *ln, u); |
|||
if (ln == NULL) { |
|||
u->close(u); |
|||
return NULL; |
|||
} |
|||
ln->base.is_readable = __is_readable; |
|||
ln->seqnum = 0; |
|||
ln->dec.thiz = ln; |
|||
ln->dec.base.on_complete = __on_downlink; |
|||
return ln; |
|||
} |
|||
|
|||
void lan_free(lan_t *ln) |
|||
{ |
|||
udp_readable_close(&ln->base); |
|||
} |
|||
|
@ -0,0 +1,117 @@ |
|||
#ifndef __LAN_H__ |
|||
#define __LAN_H__ |
|||
#include <stdint.h> |
|||
|
|||
#define NOOFTERMS 6 |
|||
|
|||
#define MSG_TYPE_CMD 0x79 |
|||
#define MSG_TYPE_AUDIO 0x7A |
|||
#define MSG_TYPE_ALARM 0x7C |
|||
|
|||
#define MSG_CMD_HANDSHAKE 0x0003 |
|||
#define MSG_RES_HANDSHAKE 0x0002 |
|||
#define MSG_CMD_PTTON 0x0007 |
|||
#define MSG_RES_PTTON 0x0006 |
|||
#define MSG_REFUSE_PTTON 0x0005 |
|||
#define MSG_CMD_PTTOFF 0x000A |
|||
#define MSG_RES_PTTOFF 0x000B |
|||
|
|||
struct MsgCmd { |
|||
uint8_t type; |
|||
uint8_t recver; |
|||
uint8_t sender; |
|||
uint8_t swid; |
|||
uint16_t msgCmd; |
|||
uint8_t termId; |
|||
uint8_t channel; |
|||
uint32_t seqNum; |
|||
} __attribute__((packed)); |
|||
|
|||
struct MsgTermStatus { |
|||
uint8_t termId; |
|||
uint8_t isDowning; |
|||
uint8_t isPtt;; |
|||
uint8_t isAlarm; |
|||
} __attribute__((packed)); |
|||
|
|||
#define MSG_AUDIO_LEN (166) |
|||
struct MsgAudio { |
|||
uint8_t type; |
|||
uint8_t recver; |
|||
uint8_t sender; |
|||
uint8_t swid; |
|||
uint8_t reserv; |
|||
uint8_t mode; |
|||
uint8_t recvChannel; |
|||
uint8_t sendChannel; |
|||
uint32_t seqNum; |
|||
uint32_t payloadLen; |
|||
uint8_t payload[0]; |
|||
} __attribute__((packed)); |
|||
|
|||
struct MsgAlarm { |
|||
uint8_t type; |
|||
uint8_t recver; |
|||
uint8_t sender; |
|||
uint8_t swid; |
|||
uint16_t reserv; |
|||
uint8_t alarmPos; |
|||
uint8_t alarmTerm; |
|||
uint32_t seqNum; |
|||
} __attribute__((packed)); |
|||
|
|||
#define RESP_PTT_OK 0x01 |
|||
#define RESP_PTT_FAILED 0x02 |
|||
|
|||
typedef struct lan lan_t; |
|||
|
|||
struct lan_audio_handler { |
|||
void (*on_audio)(struct lan_audio_handler *, struct MsgAudio *); |
|||
}; |
|||
|
|||
struct lanmsg_handler { |
|||
void (*on_ptt)(struct lanmsg_handler *, lan_t *, struct MsgCmd *hdr, uint8_t posId, int on); |
|||
void (*on_status)(struct lanmsg_handler *, uint8_t id, uint8_t status); |
|||
}; |
|||
|
|||
enum {RESP_PTT_ON, RESP_PTT_OFF}; |
|||
|
|||
lan_t *lan_new(const char *dest_addr, int port, const char *local_if); |
|||
struct codec_complete *lan_get_decode_handler(lan_t *ln); |
|||
void lan_set_msghandler(lan_t *, struct lanmsg_handler *); |
|||
void lan_set_uplink_handler(lan_t *, struct lan_audio_handler *); |
|||
int lan_ptt_response(lan_t *ln, int resp_type, struct MsgCmd *hdr, int status); |
|||
void lan_free(lan_t *); |
|||
|
|||
#if 0 |
|||
class Lan : public AudioCompleteProvider , public UdpReadable { |
|||
private: |
|||
PTTProvider *_provider; |
|||
AudioUpProvider *_audioUp; |
|||
uint32_t _myseq; |
|||
void doCmd(uint8_t *buf, int len); |
|||
void doAudio(uint8_t *buf, int len); |
|||
public: |
|||
enum {RESP_PTT_ON, RESP_PTT_OFF}; |
|||
Lan() : _provider(0), _myseq(0) {} |
|||
|
|||
int begin(const char *group_addr, int port, const char *local_if); |
|||
|
|||
virtual void isReadable(Udp &udp); |
|||
|
|||
inline int send(const void *buf, int len) { |
|||
return _udp.send(buf, len); |
|||
} |
|||
|
|||
int onResponse(int resp_type, struct MsgCmd *hdr, int status); |
|||
|
|||
void setPTTProvider(PTTProvider *_p) {_provider = _p;} |
|||
void setAudioUpProvider(AudioUpProvider *_p) {_audioUp = _p;} |
|||
|
|||
/* down complete, multiast to lan */ |
|||
virtual void onComplete(uint8_t *buf, int len); |
|||
}; |
|||
#endif |
|||
|
|||
#endif |
|||
|
@ -0,0 +1,7 @@ |
|||
#ifndef __NEWC_LOG_H__ |
|||
#define __NEWC_LOG_H__ |
|||
int log_begin(void); |
|||
int log_end(void); |
|||
int log_printf(const char *fmt,...); |
|||
#endif |
|||
|
@ -0,0 +1,10 @@ |
|||
#include "runtime.h" |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
runtime_init(); |
|||
runtime_parse_args(argc, argv); |
|||
runtime_begin(); |
|||
return runtime_loop(); |
|||
} |
|||
|
@ -1,15 +0,0 @@ |
|||
#include "Runtime.h" |
|||
#include "Timer.h" |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
Runtime.parseArgs(argc, argv); |
|||
Runtime.begin(); |
|||
if (0) { |
|||
Timer tm; |
|||
tm.begin(); |
|||
tm.active(1000); |
|||
} |
|||
return Runtime.loop(); |
|||
} |
|||
|
@ -0,0 +1,174 @@ |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <getopt.h> |
|||
#include "runtime.h" |
|||
#include "log.h" |
|||
#include "udp.h" |
|||
#include "lan.h" |
|||
#include "wan.h" |
|||
#include "codec.h" |
|||
#include "crc.h" |
|||
|
|||
#define LAN_IF "eth0" |
|||
#define LAN_FROM "192.168.9.25" |
|||
#define LAN_PORT 5600 |
|||
|
|||
#define BGE_IP "192.168.9.19" |
|||
#define BGE_PORT 6419 |
|||
#define BGE_UP_PORT 6402 |
|||
#define BGE_DOWN_PORT 6400 |
|||
|
|||
/*
|
|||
* Please disable rp_filter |
|||
* edit /etc/sysctl.conf |
|||
* |
|||
* net.ipv4.conf.default.rp_filter = 0 |
|||
* net.ipv4.conf.all.rp_filter = 0 |
|||
* |
|||
* add route for eth1 |
|||
* route add -net 192.168.31.0/24 dev eth1 |
|||
*/ |
|||
#if 1 |
|||
#define WAN_IF "eth1" |
|||
#define WAN_GROUP "225.0.0.5" |
|||
#define WAN_GROUP_PORT 8300 |
|||
#define WAN_STATUS_PORT 8100 |
|||
#else |
|||
#define WAN_IF "eth0" |
|||
#define WAN_GROUP "224.0.0.24" |
|||
#define WAN_GROUP_PORT 8300 |
|||
#define WAN_STATUS_PORT 5100 |
|||
#endif |
|||
|
|||
struct runtime Runtime; |
|||
|
|||
void runtime_init() |
|||
{ |
|||
struct event_config *config; |
|||
|
|||
Runtime._lan_if = (char *)LAN_IF; |
|||
Runtime._lan_grp_addr = (char *)LAN_FROM; |
|||
Runtime._lan_grp_port = LAN_PORT; |
|||
|
|||
Runtime._bge_ip = (char *)BGE_IP; |
|||
Runtime._bge_port = BGE_PORT; |
|||
Runtime._up_port = BGE_UP_PORT; |
|||
Runtime._down_port = BGE_DOWN_PORT; |
|||
|
|||
Runtime._wan_if = (char *)WAN_IF; |
|||
Runtime._wan_grp_addr = (char *)WAN_GROUP; |
|||
Runtime._wan_grp_port = WAN_GROUP_PORT; |
|||
Runtime._wan_status_port = WAN_STATUS_PORT; |
|||
|
|||
config = event_config_new(); |
|||
event_config_avoid_method(config, "select"); |
|||
event_config_require_features(config, EV_FEATURE_ET); |
|||
Runtime.evbase = event_base_new_with_config(config); |
|||
event_config_free(config); |
|||
log_begin(); |
|||
crc_begin(); |
|||
} |
|||
|
|||
static void print_help() |
|||
{ |
|||
log_printf("usage: cmd [option], options as:\n\t" |
|||
"--lanif, -l: set lan ethx interface, eg: \"ethx\"\n\t" |
|||
"--landest, -g: set lan multicast address, eg: \"192.168.9.25\"\n\t" |
|||
"--lanport, -p: set lan multicast port, eg: 5600\n\t" |
|||
"--wanif, -w: set lan ethx interface, eg: \"ethx\"\n\t" |
|||
"--wangrp, -r: set lan multicast address, eg: \"255.0.0.5\"\n\t" |
|||
"--wanport, -t: set lan multicast port, eg: 5600\n\t" |
|||
"--help, -h: print this message.\n"); |
|||
} |
|||
|
|||
void runtime_parse_args(int argc, char *argv[]) |
|||
{ |
|||
int c; |
|||
static struct option options[] = { |
|||
{"lanif", required_argument, NULL, 'l'}, |
|||
{"landest", required_argument, NULL, 'g'}, |
|||
{"lanport", required_argument, NULL, 'p'}, |
|||
{"wanif", required_argument, NULL, 'w'}, |
|||
{"wangrp", required_argument, NULL, 'r'}, |
|||
{"wanport", required_argument, NULL, 't'}, |
|||
{"wanstport", required_argument, NULL, 'o'}, |
|||
{"help", no_argument, NULL, 'h'}, |
|||
{NULL, 0, NULL, 0} |
|||
}; |
|||
|
|||
while ((c = getopt_long(argc, argv, "l:g:p:w:r:t:o:h", options, NULL)) != -1) { |
|||
switch (c) { |
|||
case 'l': |
|||
Runtime._lan_if = optarg; |
|||
break; |
|||
case 'g': |
|||
Runtime._lan_grp_addr = optarg; |
|||
break; |
|||
case 'p': |
|||
Runtime._lan_grp_port = atoi(optarg); |
|||
break; |
|||
case 'w': |
|||
Runtime._wan_if = optarg; |
|||
break; |
|||
case 'r': |
|||
Runtime._wan_grp_addr = optarg; |
|||
case 't': |
|||
Runtime._wan_grp_port = atoi(optarg); |
|||
break; |
|||
case 'o': |
|||
Runtime._wan_status_port = atoi(optarg); |
|||
break; |
|||
case 'h': |
|||
print_help(); |
|||
exit(0); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void runtime_begin(void) |
|||
{ |
|||
char local_if[64] = {0}; |
|||
char wan_if[64] = {0}; |
|||
|
|||
getip(Runtime._lan_if, local_if, sizeof local_if); |
|||
if ((Runtime._lan = lan_new(Runtime._lan_grp_addr, Runtime._lan_grp_port, local_if)) == NULL) { |
|||
log_printf("lan initialize failed.\n"); |
|||
exit(-1); |
|||
} |
|||
|
|||
if ((Runtime._abge = codec_new(Runtime._bge_ip, Runtime._bge_port, local_if, Runtime._down_port, Runtime._up_port)) == NULL) { |
|||
log_printf("audio bridge initialize failed.\n"); |
|||
exit(-2); |
|||
} |
|||
|
|||
getip(Runtime._wan_if, wan_if, sizeof wan_if); |
|||
if ((Runtime._wan = wan_new(Runtime._wan_grp_addr, Runtime._wan_grp_port, wan_if, Runtime._wan_status_port)) == NULL) { |
|||
log_printf("wan initialize failed.\n"); |
|||
exit(-3); |
|||
} |
|||
|
|||
if ((Runtime._cv = char_conv_new(6801, 6802)) == NULL) { |
|||
log_printf("char convter initiazlie failed.\n"); |
|||
exit(-4); |
|||
} |
|||
#if 0 |
|||
static AlarmTimer at(&_conv); |
|||
at.begin(); |
|||
at.active(1000); |
|||
#endif |
|||
codec_set_down_complete(Runtime._abge, lan_get_decode_handler(Runtime._lan)); |
|||
codec_set_up_complete(Runtime._abge, wan_get_encode_handler(Runtime._wan)); |
|||
|
|||
lan_set_uplink_handler(Runtime._lan, codec_get_uplink_handler(Runtime._abge)); |
|||
wan_set_downlink_handler(Runtime._wan, codec_get_downlink_handler(Runtime._abge)); |
|||
|
|||
lan_set_msghandler(Runtime._lan, wan_get_msghandler(Runtime._wan)); |
|||
|
|||
wan_set_alarm_handler(Runtime._wan, char_conv_get_alarm_handler(Runtime._cv)); |
|||
} |
|||
|
|||
int runtime_loop() |
|||
{ |
|||
return event_base_dispatch(Runtime.evbase); |
|||
} |
|||
|
@ -0,0 +1,43 @@ |
|||
#ifndef __RUNTIME_H__ |
|||
#define __RUNTIME_H__ |
|||
|
|||
#include <event2/event.h> |
|||
#include "lan.h" |
|||
#include "wan.h" |
|||
#include "codec.h" |
|||
#include "char_conv.h" |
|||
|
|||
struct runtime { |
|||
struct event_base *evbase; |
|||
/* lan config */ |
|||
lan_t *_lan; |
|||
char *_lan_if; |
|||
char *_lan_grp_addr; |
|||
int _lan_grp_port; |
|||
|
|||
/* audio bridge */ |
|||
codec_t * _abge; |
|||
char *_bge_ip; |
|||
int _bge_port; |
|||
int _up_port; |
|||
int _down_port; |
|||
|
|||
/* Wan */ |
|||
wan_t *_wan; |
|||
char *_wan_if; |
|||
char *_wan_grp_addr; |
|||
int _wan_grp_port; |
|||
int _wan_status_port; |
|||
|
|||
/* char conv */ |
|||
char_conv_t *_cv; |
|||
}; |
|||
|
|||
extern struct runtime Runtime; |
|||
void runtime_parse_args(int argc, char *argv[]); |
|||
void runtime_init(void); |
|||
void runtime_begin(void); |
|||
int runtime_loop(void); |
|||
|
|||
#endif |
|||
|
@ -0,0 +1,45 @@ |
|||
#include <stdlib.h> |
|||
#include "timer.h" |
|||
#include "log.h" |
|||
#include "runtime.h" |
|||
|
|||
static void __helper(int fd, short what, void *arg) |
|||
{ |
|||
struct timer *t = arg; |
|||
(void)fd; |
|||
(void)what; |
|||
t->on_timer(t); |
|||
} |
|||
|
|||
struct timer *timer_new(size_t alloc) |
|||
{ |
|||
struct timer *t; |
|||
|
|||
if (alloc < sizeof *t) |
|||
return NULL; |
|||
|
|||
t = calloc(1, alloc); |
|||
event_assign(&t->_evt, Runtime.evbase, -1, EV_TIMEOUT | EV_PERSIST, __helper, t); |
|||
return t; |
|||
} |
|||
|
|||
void timer_active(struct timer * t, int ms) |
|||
{ |
|||
struct timeval tv; |
|||
|
|||
tv.tv_sec = ms / 1000; |
|||
tv.tv_usec = ms % 1000; |
|||
|
|||
event_add(&t->_evt, &tv); |
|||
} |
|||
|
|||
void timer_deactive(struct timer *t) |
|||
{ |
|||
event_del(&t->_evt); |
|||
} |
|||
|
|||
void timer_free(struct timer *t) |
|||
{ |
|||
free(t); |
|||
} |
|||
|
@ -0,0 +1,17 @@ |
|||
#ifndef __ETIMER_H__ |
|||
#define __ETIMER_H__ |
|||
|
|||
#include <event2/event.h> |
|||
#include <event2/event_struct.h> |
|||
struct timer { |
|||
struct event _evt; |
|||
void (*on_timer)(struct timer *); |
|||
}; |
|||
|
|||
struct timer *timer_new(size_t alloc); |
|||
void timer_active(struct timer *, int ms); |
|||
void timer_deactive(struct timer *); |
|||
void timer_free(struct timer *); |
|||
|
|||
#endif |
|||
|
@ -0,0 +1,18 @@ |
|||
#ifndef __UDP_NEWC_H__ |
|||
#define __UDP_NEWC_H__ |
|||
typedef struct udp udp_t; |
|||
struct udp { |
|||
int sock; |
|||
int (*bind)(udp_t *, const char *local_ip, int local_port); |
|||
int (*connect)(udp_t *, const char *remote_ip, int remote_port); |
|||
int (*send)(udp_t *, void *buf, int len); |
|||
int (*recv)(udp_t *, void *buf, int len); |
|||
int (*close)(udp_t *); |
|||
}; |
|||
|
|||
udp_t *udp_open(void); |
|||
udp_t *udp_open_mcast(const char *group, int port, const char *local_if); |
|||
int getip(const char *ethx, char *addr, int len); |
|||
|
|||
#endif |
|||
|
@ -0,0 +1,33 @@ |
|||
#include <stdlib.h> |
|||
#include "udp_readable.h" |
|||
#include "runtime.h" |
|||
|
|||
static void __helper(int fd , short what, void *arg) |
|||
{ |
|||
udp_readable_t *ur = arg; |
|||
(void)fd; |
|||
if (what & EV_READ) { |
|||
ur->is_readable(ur); |
|||
} |
|||
} |
|||
|
|||
udp_readable_t *udp_readable_open(size_t alloc_size, udp_t *u) |
|||
{ |
|||
udp_readable_t *ur; |
|||
|
|||
if (alloc_size < sizeof *ur) |
|||
return NULL; |
|||
ur = calloc(1, alloc_size); |
|||
ur->udp = u; |
|||
event_assign(&ur->evt, Runtime.evbase, u->sock, EV_READ | EV_PERSIST, __helper, ur); |
|||
event_add(&ur->evt, NULL); |
|||
return ur; |
|||
} |
|||
|
|||
void udp_readable_close(udp_readable_t *ur) |
|||
{ |
|||
event_del(&ur->evt); |
|||
ur->udp->close(ur->udp); |
|||
free(ur); |
|||
} |
|||
|
@ -0,0 +1,17 @@ |
|||
#ifndef __UDP_READABLE_H__ |
|||
#define __UDP_READABLE_H__ |
|||
#include <event2/event.h> |
|||
#include <event2/event_struct.h> |
|||
#include "udp.h" |
|||
|
|||
typedef struct udp_readable udp_readable_t; |
|||
struct udp_readable { |
|||
struct event evt; |
|||
udp_t *udp; |
|||
void (*is_readable)(udp_readable_t *); |
|||
}; |
|||
|
|||
udp_readable_t *udp_readable_open(size_t alloc_size, udp_t *u); |
|||
void udp_readable_close(udp_readable_t *); |
|||
#endif |
|||
|
@ -0,0 +1,181 @@ |
|||
#include <time.h> |
|||
#include <unistd.h> |
|||
#include <errno.h> |
|||
#include <string.h> |
|||
#include "udp_readable.h" |
|||
#include "log.h" |
|||
#include "codec.h" |
|||
#include "wan.h" |
|||
#include "lan.h" |
|||
|
|||
struct encode_handler { |
|||
struct codec_complete base; |
|||
wan_t *thiz; |
|||
}; |
|||
|
|||
struct wanmsg_handler { |
|||
struct lanmsg_handler base; |
|||
wan_t *thiz; |
|||
}; |
|||
|
|||
struct wan { |
|||
struct udp_readable base; |
|||
struct encode_handler enc; |
|||
struct wanmsg_handler msghdr; |
|||
udp_t *stsock; |
|||
struct wan_audio_handler *_downlink; |
|||
struct wan_alarm_handler *_alarm; |
|||
struct WanStatusType _stBuf; |
|||
uint32_t _stSeq; |
|||
}; |
|||
|
|||
struct lanmsg_handler *wan_get_msghandler(wan_t *wn) |
|||
{ |
|||
return &wn->msghdr.base; |
|||
} |
|||
|
|||
void wan_set_downlink_handler(wan_t *wn, struct wan_audio_handler *h) |
|||
{ |
|||
wn->_downlink = h; |
|||
} |
|||
|
|||
void wan_set_alarm_handler(wan_t *wan, struct wan_alarm_handler *h) |
|||
{ |
|||
wan->_alarm = h; |
|||
} |
|||
|
|||
struct codec_complete *wan_get_encode_handler(wan_t *wn) |
|||
{ |
|||
return &wn->enc.base; |
|||
} |
|||
|
|||
static void __is_readable(udp_readable_t *ur) |
|||
{ |
|||
uint8_t data[1500] = {0}; |
|||
int len; |
|||
wan_t *wn = (wan_t *)ur; |
|||
udp_t *u = ur->udp; |
|||
|
|||
if ((len = u->recv(u, data, sizeof data)) <= 0) |
|||
return; |
|||
|
|||
#if 0 |
|||
Log.printf("Wan recv: %d bytes\n", len); |
|||
for (int i = 0; i < len; ++i) { |
|||
Log.printf("%02x%c", data[i], ((i + 1) % 16) ? ' ' : '\n'); |
|||
} |
|||
Log.printf("\n"); |
|||
#endif |
|||
|
|||
if ((data[0] == 0xAA) && (data[1] == 0x55)) { |
|||
if ((len == 32) && (data[6] == 0x91)) { |
|||
struct WanAudioType *wat = (struct WanAudioType *)data; |
|||
wn->_downlink->on_audio(wn->_downlink, wat); |
|||
} |
|||
} |
|||
/*XXX: if alarming , call _alarm->onAlarm() */ |
|||
if ((data[0] == 0xAC) && (data[1] == 0x93)) { |
|||
if ((len == 64) && (data[13] == 0xF0)) { |
|||
struct WanAlarmType *wmt = (struct WanAlarmType *)data; |
|||
wn->_alarm->on_alarm(wn->_alarm, wmt); |
|||
} |
|||
} |
|||
} |
|||
|
|||
static void __on_uplink(struct codec_complete *cc, uint8_t *buf, int len) |
|||
{ |
|||
struct encode_handler *eh = (struct encode_handler *)cc; |
|||
udp_t *u = eh->thiz->base.udp; |
|||
u->send(u, buf, len); |
|||
} |
|||
|
|||
static void __on_ptt(struct lanmsg_handler *lh, lan_t *ln, struct MsgCmd *hdr, uint8_t posId, int on) |
|||
{ |
|||
struct wanmsg_handler *wh = (struct wanmsg_handler *)lh; |
|||
wan_t *wn = wh->thiz; |
|||
|
|||
if (on) { |
|||
} else { |
|||
} |
|||
|
|||
lan_ptt_response(ln, on ? RESP_PTT_ON : RESP_PTT_OFF, hdr, RESP_PTT_OK); |
|||
} |
|||
|
|||
static void __on_status(struct lanmsg_handler *lh, uint8_t id, uint8_t status) |
|||
{ |
|||
struct wanmsg_handler *wh = (struct wanmsg_handler *)lh; |
|||
int len = 0; |
|||
uint8_t *sbuf; |
|||
wan_t *wn = wh->thiz; |
|||
|
|||
wn->_stBuf.destId = status ? id : 0; |
|||
/*
|
|||
* 0: don't start |
|||
* 1: playing |
|||
* 2: idle |
|||
*/ |
|||
wn->_stBuf.status = status ? 0x01 : 0x02; |
|||
wn->_stBuf.time = htonl(time(NULL)); |
|||
wn->_stBuf.seq = htonl(++wn->_stSeq); |
|||
uint32_t cs = 0; |
|||
len = sizeof wn->_stBuf - 2; |
|||
sbuf = (uint8_t *)&wn->_stBuf; |
|||
for (int x = 0; x < len; ++x) { |
|||
cs += sbuf[x]; |
|||
} |
|||
wn->_stBuf.checkNum = cs & 0xff; |
|||
|
|||
len = wn->stsock->send(wn->stsock, &wn->_stBuf, sizeof wn->_stBuf); |
|||
if (len < 0) { |
|||
log_printf("%s:%d errno (%d) %s\n", __FILE__, __LINE__, errno, strerror(errno)); |
|||
} |
|||
// Log.printf("status sending %d bytes\n", len);
|
|||
} |
|||
|
|||
wan_t* wan_new(const char *group_addr, int port, const char *wlan_if, int stport) |
|||
{ |
|||
wan_t *wn; |
|||
udp_t *udp, *sts; |
|||
|
|||
log_printf("Wan group: %s, port: %d, wan: %s\n", group_addr, port, wlan_if); |
|||
if ((udp = udp_open_mcast(group_addr, port, wlan_if)) == NULL) { |
|||
log_printf("'%s[%d]: can't create multicast socket\n", __FILE__, __LINE__); |
|||
return NULL; |
|||
} |
|||
|
|||
if ((sts = udp_open_mcast(group_addr, stport, wlan_if)) == NULL) { |
|||
log_printf("'%s[%d]: can't create status multicast socket\n", __FILE__, __LINE__); |
|||
udp->close(udp); |
|||
return NULL; |
|||
} |
|||
wn = (wan_t *)udp_readable_open(sizeof *wn, udp); |
|||
wn->stsock = sts; |
|||
wn->_stSeq = 0; |
|||
wn->enc.thiz = wn; |
|||
wn->enc.base.on_complete = __on_uplink; |
|||
wn->base.is_readable = __is_readable; |
|||
wn->msghdr.thiz = wn; |
|||
wn->msghdr.base.on_ptt = __on_ptt; |
|||
wn->msghdr.base.on_status = __on_status; |
|||
|
|||
memset(&wn->_stBuf, 0, sizeof wn->_stBuf); |
|||
wn->_stBuf.id1 = 0xAC; |
|||
wn->_stBuf.id2 = 0x93; |
|||
wn->_stBuf.id3 = 0x27; |
|||
wn->_stBuf.id4 = 0x21; |
|||
wn->_stBuf.srcPosId = 0xB1; |
|||
wn->_stBuf.srcSwId = 0xD8; |
|||
wn->_stBuf.destSwId = 0xE8; |
|||
wn->_stBuf.initPosId = 0xB1; |
|||
wn->_stBuf.contentId = 0xF3; |
|||
wn->_stBuf.id5 = 0x14; |
|||
|
|||
return wn; |
|||
} |
|||
|
|||
void wan_free(wan_t *wn) |
|||
{ |
|||
wn->stsock->close(wn->stsock); |
|||
udp_readable_close(&wn->base); |
|||
} |
|||
|
Loading…
Reference in new issue