package server import ( "bytes" "context" "encoding/binary" "net" "time" "git.espin.casa/albert/cml04-gdm-int/pkg/api" "git.espin.casa/albert/cml04-l2-rsm-in/internal/helpers" "git.espin.casa/albert/cml04-l2-rsm-in/internal/service" "git.espin.casa/albert/cml04-l2-rsm-in/internal/types" "git.espin.casa/albert/logger" ) type Server struct { address string svc service.IService log logger.LoggerAdapter } type Client struct { conn net.Conn svc service.IService log logger.LoggerAdapter } func (client *Client) handleRequest() { // telegram bytes buffer holder 4096 maximun telegram size defined by SMS telegramBytes := bytes.NewBuffer(make([]byte, 4096)) for { _, err := client.conn.Read(telegramBytes.Bytes()) if err != nil { client.log.Error("reading telegram failed", err, logger.LogFields{}) return } // interpret first 24 bytes as header header := &types.TelegramHeader{} headerReader := bytes.NewReader(telegramBytes.Bytes()[:24]) if err := binary.Read(headerReader, binary.LittleEndian, header); err != nil { client.log.Error("interpreting telegram header failed", err, logger.LogFields{}) return } // switch telegram id switch header.TelegramID { // handle telegram data case types.BdReqTelegramID: // read telegram data telegramData := &types.BdRequestTelegram{} if err := binary.Read(telegramBytes, binary.LittleEndian, telegramData); err != nil { client.log.Error("reading telegram content failed", err, logger.LogFields{}) return } // clean roll set id id := helpers.CleanString(string(telegramData.BdRollSetId[:])) // api request roll req := &api.BdRollDataReq{ Sender: "cml04-l2-rsm", RollId: id, TimeStamp: time.Now().UTC().Format(time.RFC3339), } // create context ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // handle telegram data res, err := client.handleBdDataRequest(ctx, req) if err != nil { client.log.Error("processing telegram failed", err, logger.LogFields{}) return } // publish response if err := client.handlePublishBdRollData(ctx, res); err != nil { client.log.Error("publishing BD roll data failed", err, logger.LogFields{}) return } case types.UrReqTelegramID: // read telegram data telegramData := &types.UrRequestTelegram{} if err := binary.Read(telegramBytes, binary.LittleEndian, telegramData); err != nil { client.log.Error("reading telegram content failed", err, logger.LogFields{}) return } // clean roll set id id := helpers.CleanString(string(telegramData.UrRollSetId[:])) // api request roll req := &api.UrRollDataReq{ Sender: "cml04-l2-rsm", RollId: id, TimeStamp: time.Now().UTC().Format(time.RFC3339), } // handle telegram data res, err := client.handleUrReqTelegram(context.Background(), req) if err != nil { client.log.Error("processing telegram failed", err, logger.LogFields{}) return } // publish response if err := client.handlePublishUrRollData(context.Background(), res); err != nil { client.log.Error("publishing UR roll data failed", err, logger.LogFields{}) return } case types.EdReqTelegramID: // read telegram data telegramData := &types.EdRequestTelegram{} if err := binary.Read(telegramBytes, binary.LittleEndian, telegramData); err != nil { client.log.Error("reading telegram content failed", err, logger.LogFields{}) return } // clean roll set id id := helpers.CleanString(string(telegramData.EdRollSetId[:])) // api request roll req := &api.EdRollDataReq{ Sender: "cml04-l2-rsm", RollId: id, TimeStamp: time.Now().UTC().Format(time.RFC3339), } // handle telegram data res, err := client.handleEdReqTelegram(context.Background(), req) if err != nil { client.log.Error("processing telegram failed", err, logger.LogFields{}) return } // publish response if err := client.handlePublishEdRollData(context.Background(), res); err != nil { client.log.Error("publishing ED roll data failed", err, logger.LogFields{}) return } case types.UfReqTelegramID: // read telegram data telegramData := &types.UfRequestTelegram{} if err := binary.Read(telegramBytes, binary.LittleEndian, telegramData); err != nil { client.log.Error("reading telegram content failed", err, logger.LogFields{}) return } // clean roll set id id := helpers.CleanString(string(telegramData.UfRollSetId[:])) // api request roll req := &api.UfRollDataReq{ Sender: "cml04-l2-rsm", RollId: id, TimeStamp: time.Now().UTC().Format(time.RFC3339), } // handle telegram data res, err := client.handleUfReqTelegram(context.Background(), req) if err != nil { client.log.Error("processing telegram failed", err, logger.LogFields{}) return } // publish response if err := client.handlePublishUfRollData(context.Background(), res); err != nil { client.log.Error("publishing UF roll data failed", err, logger.LogFields{}) return } } } } func (client *Client) handlePublishBdRollData(ctx context.Context, data *api.BdRollDataRes) error { return client.svc.PublishBdRollData(ctx, data.GetRollData()) } func (client *Client) handlePublishUrRollData(ctx context.Context, data *api.UrRollDataRes) error { return client.svc.PublishUrRollData(ctx, data.GetRollData()) } func (client *Client) handlePublishEdRollData(ctx context.Context, data *api.EdRollDataRes) error { return client.svc.PublishEdRollData(ctx, data.GetRollData()) } func (client *Client) handlePublishUfRollData(ctx context.Context, data *api.UfRollDataRes) error { return client.svc.PublishUfRollData(ctx, data.GetRollData()) } func (client *Client) handleBdDataRequest(ctx context.Context, req *api.BdRollDataReq) (*api.BdRollDataRes, error) { return client.svc.BdReqTelegram(ctx, req) } func (client *Client) handleUrReqTelegram(ctx context.Context, req *api.UrRollDataReq) (*api.UrRollDataRes, error) { return client.svc.UrReqTelegram(ctx, req) } func (client *Client) handleEdReqTelegram(ctx context.Context, req *api.EdRollDataReq) (*api.EdRollDataRes, error) { return client.svc.EdReqTelegram(ctx, req) } func (client *Client) handleUfReqTelegram(ctx context.Context, telegramData *api.UfRollDataReq) (*api.UfRollDataRes, error) { return client.svc.UfReqTelegram(ctx, telegramData) } func (server *Server) Run() error { // create tcp listener listener, err := net.Listen("tcp", server.address) if err != nil { return err } // close on exit defer listener.Close() // accept incoming connections for { // accept connection conn, err := listener.Accept() if err != nil { return err } // create new client client := &Client{ conn: conn, svc: server.svc, log: server.log, } // handle client go client.handleRequest() } } func NewServer(address string, log logger.LoggerAdapter, svc service.IService) *Server { return &Server{ address: address, svc: svc, log: log, } }