sess/session.go
func (h *Handler) StartSession(product, productPassword,
	clientKey, ip string, port uint16) (*data.Offering, error) {
	logger := h.logger.Add("method", "StartSession", "product", product,
		"clientKey", clientKey, "ip", ip, "port", port)

	logger.Info("session start request")

	prod, err := h.checkProductPassword(logger, product, productPassword)
	if err != nil {
		return nil, err
	}

	ch, err := h.findClientChannel(logger, prod, clientKey, true)
	if err != nil {
		return nil, err
	}

	var offer data.Offering
	if err := h.db.FindByPrimaryKeyTo(&offer, ch.Offering); err != nil {
		logger.Error(err.Error())
		return nil, ErrInternal
	}

	now := time.Now()

	var ipPtr *string
	if len(ip) != 0 {
		ipPtr = pointer.ToString(ip)
	}

	var portPtr *uint16
	if port != 0 {
		portPtr = pointer.ToUint16(port)
	}

	err = h.db.InTransaction(func(tx *reform.TX) error {
		sess := data.Session{
			ID:            util.NewUUID(),
			Channel:       ch.ID,
			Started:       now,
			LastUsageTime: now,
			ClientIP:      ipPtr,
			ClientPort:    portPtr,
		}
		if err := tx.Insert(&sess); err != nil {
			return err
		}

		if ch.ServiceStatus == data.ServiceActivating {
			err := job.AddWithData(h.queue, tx,
				data.JobClientCompleteServiceTransition,
				data.JobChannel, ch.ID, data.JobSessionServer,
				data.ServiceActive)
			if err != nil && err != job.ErrDuplicatedJob {
				return err
			}
		}

		return nil
	})
	if err != nil {
		logger.Error(err.Error())
		return nil, ErrInternal
	}

	return &offer, nil
}
func (h *Handler) StartSession(product, productPassword,
	clientKey, ip string, port uint16) (*data.Offering, error) {
	logger := h.logger.Add("method", "StartSession", "product", product,
		"clientKey", clientKey, "ip", ip, "port", port)

	logger.Info("session start request")

	prod, err := h.checkProductPassword(logger, product, productPassword)
	if err != nil {
		return nil, err
	}

	ch, err := h.findClientChannel(logger, prod, clientKey, true)
	if err != nil {
		return nil, err
	}

	var offer data.Offering
	if err := h.db.FindByPrimaryKeyTo(&offer, ch.Offering); err != nil {
		logger.Error(err.Error())
		return nil, ErrInternal
	}

	now := time.Now()

	var ipPtr *string
	if len(ip) != 0 {
		ipPtr = pointer.ToString(ip)
	}

	var portPtr *uint16
	if port != 0 {
		portPtr = pointer.ToUint16(port)
	}

	err = h.db.InTransaction(func(tx *reform.TX) error {
		sess := data.Session{
			ID:            util.NewUUID(),
			Channel:       ch.ID,
			Started:       now,
			LastUsageTime: now,
			ClientIP:      ipPtr,
			ClientPort:    portPtr,
		}
		if err := tx.Insert(&sess); err != nil {
			return err
		}

		if ch.ServiceStatus == data.ServiceActivating {
			err := job.AddWithData(h.queue, tx,
				data.JobClientCompleteServiceTransition,
				data.JobChannel, ch.ID, data.JobSessionServer,
				data.ServiceActive)
			if err != nil && err != job.ErrDuplicatedJob {
				return err
			}
		}

		return nil
	})
	if err != nil {
		logger.Error(err.Error())
		return nil, ErrInternal
	}

	return &offer, nil
}
// StartSession creates a new client session.