1
0
mirror of https://github.com/mainflux/mainflux.git synced 2025-04-27 13:48:49 +08:00
Ivan Milošević 66d3da0531
NOISSUE - Add SMPP notifier (#1464)
* Add SMPP notifier

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* fix readme
remove env file

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* resolve conversations

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* Remove debug log

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* Rename transmiter and transformer fields in struct

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* fix typo

Signed-off-by: Ivan Milosevic <iva@blokovi.com>
2021-10-06 14:34:23 +02:00

162 lines
3.3 KiB
Go

// Copyright 2015 go-smpp authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package smpp
import (
"bufio"
"bytes"
"crypto/tls"
"errors"
"io"
"net"
"sync"
"github.com/fiorix/go-smpp/smpp/pdu"
)
var (
// ErrNotConnected is returned on attempts to use a dead connection.
ErrNotConnected = errors.New("not connected")
// ErrNotBound is returned on attempts to use a Transmitter,
// Receiver or Transceiver before calling Bind.
ErrNotBound = errors.New("not bound")
// ErrTimeout is returned when we've reached timeout while waiting for response.
ErrTimeout = errors.New("timeout waiting for response")
)
// Conn is an SMPP connection.
type Conn interface {
Reader
Writer
Closer
}
// Reader is the interface that wraps the basic Read method.
type Reader interface {
// Read reads PDU binary data off the wire and returns it.
Read() (pdu.Body, error)
}
// Writer is the interface that wraps the basic Write method.
type Writer interface {
// Write serializes the given PDU and writes to the connection.
Write(w pdu.Body) error
}
// Closer is the interface that wraps the basic Close method.
type Closer interface {
// Close terminates the connection.
Close() error
}
// Dial dials to the SMPP server and returns a Conn, or error.
// TLS is only used if provided.
func Dial(addr string, TLS *tls.Config) (Conn, error) {
if addr == "" {
addr = "localhost:2775"
}
fd, err := net.Dial("tcp", addr)
if err != nil {
return nil, err
}
if TLS != nil {
fd = tls.Client(fd, TLS)
}
c := &conn{
rwc: fd,
r: bufio.NewReader(fd),
w: bufio.NewWriter(fd),
}
return c, nil
}
// conn provides the basics of a single client connection and
// implements the Conn interface.
type conn struct {
rwc net.Conn
r *bufio.Reader
w *bufio.Writer
}
// Read implements the Conn interface.
func (c *conn) Read() (pdu.Body, error) {
return pdu.Decode(c.r)
}
// Write implements the Conn interface.
func (c *conn) Write(w pdu.Body) error {
var b bytes.Buffer
err := w.SerializeTo(&b)
if err != nil {
return err
}
_, err = io.Copy(c.w, &b)
if err != nil {
return err
}
return c.w.Flush()
}
// Close implements the Conn interface.
func (c *conn) Close() error {
return c.rwc.Close()
}
// connSwitch implements the Conn interface but allows switching
// the actual Conn object it wraps.
//
// If no Conn is available, any attempt to Read/Write/Close
// returns ErrNotConnected.
type connSwitch struct {
mu sync.Mutex
c Conn
}
// Set sets the underlying Conn with the given one.
// If we hold a Conn already, it will be closed before switching over.
func (cs *connSwitch) Set(c Conn) {
cs.mu.Lock()
if cs.c != nil {
cs.c.Close()
}
cs.c = c
cs.mu.Unlock()
}
// Read implements the Conn interface.
func (cs *connSwitch) Read() (pdu.Body, error) {
cs.mu.Lock()
conn := cs.c
cs.mu.Unlock()
if conn == nil {
return nil, ErrNotConnected
}
return conn.Read()
}
// Write implements the Conn interface.
func (cs *connSwitch) Write(w pdu.Body) error {
cs.mu.Lock()
defer cs.mu.Unlock()
if cs.c == nil {
return ErrNotConnected
}
return cs.c.Write(w)
}
// Close implements the Conn interface.
func (cs *connSwitch) Close() error {
cs.mu.Lock()
defer cs.mu.Unlock()
if cs.c == nil {
return ErrNotConnected
}
err := cs.c.Close()
cs.c = nil
return err
}