databag/net/server/internal/sturn/message.go

286 lines
6.8 KiB
Go
Raw Normal View History

2023-04-07 19:30:05 +00:00
package sturn
import (
"net"
"fmt"
2023-04-07 22:02:31 +00:00
"errors"
"bytes"
"strings"
"strconv"
2023-04-07 19:30:05 +00:00
)
func readMessage(buf []byte) (error, *SturnMessage) {
2023-04-07 22:02:31 +00:00
if len(buf) < 20 {
return errors.New("invalid header size"), nil
}
if buf[0] & 0xC0 != 0 {
return errors.New("invalid message prefix"), nil
}
magic := []byte{0x21, 0x12, 0xA4, 0x42 }
if !bytes.Equal(magic, buf[4:8]) {
return errors.New("invalid message cookie"), nil
}
atrLength := int(buf[2]) * 256 + int(buf[3])
if atrLength + 20 != len(buf) {
return errors.New("invalid message length"), nil
}
class, method := getMessageType(buf[0], buf[1]);
transaction := buf[8:20];
var attributes []SturnAttribute
var pos int = 0
for pos < atrLength {
err, attr, n := readAttribute(buf, pos + 20)
if err != nil {
return err, nil
}
pos += n
attributes = append(attributes, *attr);
}
2023-04-07 19:30:05 +00:00
2023-04-07 22:02:31 +00:00
return nil, &SturnMessage{
class: class,
method: method,
transaction: transaction,
attributes: attributes,
}
}
2023-04-07 19:30:05 +00:00
func writeMessage(msg *SturnMessage, buf []byte) (error, int) {
2023-04-07 22:02:31 +00:00
if len(buf) < 20 {
return errors.New("invalid buffer length"), 0
}
2023-04-10 08:20:44 +00:00
2023-04-07 22:02:31 +00:00
// set prefix
buf[0], buf[1] = setMessageType(msg.class, msg.method)
// init size
buf[2] = 0x00
buf[3] = 0x00
// set cookie
buf[4] = 0x21
buf[5] = 0x12
buf[6] = 0xA4
buf[7] = 0x42
// set transaction
for i := 0; i < 12; i++ {
buf[8 + i] = msg.transaction[i];
}
// set each attribute
pos := 0
for _, attribute := range msg.attributes {
err, n := writeAttribute(&attribute, buf, 20 + pos);
if err != nil {
return err, 0
}
pos += n;
// set size
buf[2] = byte((pos >> 8) % 256);
buf[3] = byte(pos % 256);
}
return nil, pos + 20;
2023-04-07 19:30:05 +00:00
}
func (s *Sturn) handleMessage(buf []byte, addr net.Addr) {
err, msg := readMessage(buf);
if err != nil {
2023-04-10 08:20:44 +00:00
fmt.Println(addr.String(), buf);
2023-04-07 19:30:05 +00:00
fmt.Println(err);
return
}
if msg == nil {
return
}
if msg.class == CLSRequest && msg.method == MEHBinding {
2023-04-10 08:20:44 +00:00
fmt.Println("stun/turn binding request");
2023-04-08 05:59:09 +00:00
s.handleBindingRequest(msg, addr);
2023-04-07 19:30:05 +00:00
} else if msg.class == CLSRequest && msg.method == MEHAllocate {
2023-04-10 08:20:44 +00:00
fmt.Println("stun/turn allocate request");
2023-04-08 05:59:09 +00:00
s.handleAllocateRequest(msg, addr);
2023-04-10 08:20:44 +00:00
} else if msg.class == CLSRequest && msg.method == MEHRefresh {
fmt.Println("stun/turn refresh request");
s.handleRefreshRequest(msg, addr);
} else if msg.class == CLSRequest && msg.method == MEHCreatePermission {
fmt.Println("stun/turn create permission request");
s.handleCreatePermissionRequest(msg, addr);
} else if msg.class == CLSIndication && msg.method == MEHSend {
fmt.Println("stun/turn send");
s.handleSendIndication(msg, addr);
2023-04-07 19:30:05 +00:00
} else {
fmt.Println("unsupported message", buf);
}
}
2023-04-10 08:20:44 +00:00
func (s *Sturn) handleCreatePermissionRequest(msg *SturnMessage, addr net.Addr) {
2023-04-10 17:07:52 +00:00
fmt.Println(addr.String(), msg);
var attributes []SturnAttribute
attributes = append(attributes, SturnAttribute{
atrType: ATRMessageIntegrity,
});
response := &SturnMessage{
class: CLSResponse,
method: MEHCreatePermission,
transaction: msg.transaction,
attributes: attributes,
};
err, n := writeMessage(response, s.buf);
if err != nil {
fmt.Printf("failed to write stun response");
} else {
(*s.conn).WriteTo(s.buf[:n], addr);
fmt.Println("PERM>", s.buf[:n]);
}
return
2023-04-10 08:20:44 +00:00
}
func (s *Sturn) handleSendIndication(msg *SturnMessage, addr net.Addr) {
2023-04-10 17:07:52 +00:00
//fmt.Println(addr.String(), msg);
2023-04-10 08:20:44 +00:00
}
2023-04-08 05:59:09 +00:00
func (s *Sturn) handleBindingRequest(msg *SturnMessage, addr net.Addr) {
2023-04-07 22:02:31 +00:00
address := strings.Split(addr.String(), ":")
ip := address[0];
port, _ := strconv.Atoi(address[1]);
var attributes []SturnAttribute
attributes = append(attributes, SturnAttribute{
atrType: ATRXorMappedAddress,
byteValue: FAMIPv4,
intValue: int32(port),
strValue: ip,
});
response := &SturnMessage{
class: CLSResponse,
method: MEHBinding,
transaction: msg.transaction,
attributes: attributes,
};
err, n := writeMessage(response, s.buf);
if err != nil {
fmt.Printf("failed to write stun response");
} else {
(*s.conn).WriteTo(s.buf[:n], addr);
}
2023-04-08 05:59:09 +00:00
return
}
2023-04-10 08:20:44 +00:00
func (s *Sturn) handleRefreshRequest(msg *SturnMessage, addr net.Addr) {
response := &SturnMessage{
class: CLSResponse,
method: MEHRefresh,
transaction: msg.transaction,
attributes: []SturnAttribute{},
};
err, n := writeMessage(response, s.buf);
if err != nil {
fmt.Printf("failed to write stun response");
} else {
(*s.conn).WriteTo(s.buf[:n], addr);
}
return
}
2023-04-08 05:59:09 +00:00
func (s *Sturn) sendAllocateError(msg *SturnMessage, addr net.Addr) {
var attributes []SturnAttribute
attributes = append(attributes, SturnAttribute{
atrType: ATRErrorCode,
intValue: 400,
})
attributes = append(attributes, SturnAttribute{
atrType: ATRNonce,
strValue: "",
})
attributes = append(attributes, SturnAttribute{
atrType: ATRRealm,
2023-04-09 18:32:18 +00:00
strValue: "databag.dweb",
2023-04-08 05:59:09 +00:00
})
response := &SturnMessage{
class: CLSError,
method: MEHAllocate,
transaction: msg.transaction,
attributes: attributes,
};
err, n := writeMessage(response, s.buf);
if err != nil {
fmt.Printf("failed to write stun response");
} else {
(*s.conn).WriteTo(s.buf[:n], addr);
}
2023-04-07 19:30:05 +00:00
}
2023-04-08 05:59:09 +00:00
func (s *Sturn) handleAllocateRequest(msg *SturnMessage, addr net.Addr) {
username := getAttribute(msg, ATRUsername);
if username == nil {
s.sendAllocateError(msg, addr);
return;
}
2023-04-09 18:32:18 +00:00
relayPort, err := s.getRelayPort();
2023-04-08 05:59:09 +00:00
if err != nil {
fmt.Println(err);
s.sendAllocateError(msg, addr)
return
}
2023-04-09 18:32:18 +00:00
address := strings.Split(addr.String(), ":")
ip := address[0];
port, _ := strconv.Atoi(address[1]);
var attributes []SturnAttribute
attributes = append(attributes, SturnAttribute{
atrType: ATRXorRelayedAddress,
byteValue: FAMIPv4,
intValue: int32(relayPort),
2023-04-10 17:07:52 +00:00
strValue: "192.168.13.233",
//strValue: "98.234.232.221",
2023-04-09 18:32:18 +00:00
});
attributes = append(attributes, SturnAttribute{
atrType: ATRLifetime,
intValue: int32(600),
});
attributes = append(attributes, SturnAttribute{
atrType: ATRXorMappedAddress,
byteValue: FAMIPv4,
intValue: int32(port),
strValue: ip,
});
attributes = append(attributes, SturnAttribute{
atrType: ATRMessageIntegrity,
});
response := &SturnMessage{
class: CLSResponse,
method: MEHAllocate,
transaction: msg.transaction,
attributes: attributes,
};
err, n := writeMessage(response, s.buf);
if err != nil {
fmt.Printf("failed to write stun response");
} else {
(*s.conn).WriteTo(s.buf[:n], addr);
}
2023-04-08 05:59:09 +00:00
return
2023-04-07 19:30:05 +00:00
}
2023-04-08 05:59:09 +00:00
func getAttribute(msg *SturnMessage, atrType int) (attr *SturnAttribute) {
for _, attribute := range msg.attributes {
if attribute.atrType == ATRUsername {
attr = &attribute;
}
}
return
}