diff --git a/registry/epp/dbreg/poll.go b/registry/epp/dbreg/poll.go index 661ef44..7ac6724 100644 --- a/registry/epp/dbreg/poll.go +++ b/registry/epp/dbreg/poll.go @@ -22,42 +22,63 @@ func CreatePollMessage(db *server.DBConn, registrar_id uint, msg_type int) (uint return poll_msg_id, err } -func GetPollMessageCount(db *server.DBConn, regid uint) (uint, error) { +type PollMsg struct { + db *server.DBConn + regid uint + extended bool +} + +func NewPollMsg(db *server.DBConn, regid uint) *PollMsg { + return &PollMsg{ + db:db, + regid:regid, + } +} + +func (p *PollMsg) SetExtended(extended bool) *PollMsg { + p.extended = extended + return p +} + +func (p *PollMsg) GetPollMessageCount() (uint, error) { query := "SELECT count(*) FROM message WHERE seen='f' " + "and clid=$1::bigint and exdate > now() and msgtype in(22,1)" - row := db.QueryRow(query, regid) + row := p.db.QueryRow(query, p.regid) var count uint err := row.Scan(&count) return count, err } -func getPollTransferObject(db *server.DBConn, msgid uint) (*PollMessage, error) { +func (p *PollMsg) getPollTransferObject(msgid uint) (*PollMessage, error) { var poll_msg PollMessage - row := db.QueryRow("SELECT request_id, status FROM epp_transfer_request_state_change "+ + row := p.db.QueryRow("SELECT request_id, status FROM epp_transfer_request_state_change "+ "WHERE msgid=$1::integer", msgid) var requestid, status uint err := row.Scan(&requestid, &status) if err != nil { return &poll_msg, err } - find_transfer := FindTransferRequest{TrID:requestid} - transfer_obj, err := find_transfer.Exec(db) - if err != nil { - return &poll_msg, err + + if p.extended { + find_transfer := FindTransferRequest{TrID:requestid} + transfer_obj, err := find_transfer.Exec(p.db) + if err != nil { + return &poll_msg, err + } + poll_msg.Content = transfer_obj } poll_msg.Msgid = msgid - poll_msg.Msg = "changed state" - poll_msg.Content = transfer_obj + poll_msg.Msg = GetTransferMsg(status) return &poll_msg, nil } -func GetFirstUnreadPollMessage(db *server.DBConn, regid uint) (*PollMessage, error) { +func (p *PollMsg) GetFirstUnreadPollMessage() (*PollMessage, error) { query := "SELECT id, msgtype, crdate, exdate FROM message WHERE seen='f' " + "and clid=$1::bigint and exdate > now() and msgtype in(22,1) ORDER BY id LIMIT 1" - row := db.QueryRow(query, regid) + row := p.db.QueryRow(query, p.regid) var msgtype, msgid uint var crdate, exdate pgtype.Timestamp @@ -69,14 +90,18 @@ func GetFirstUnreadPollMessage(db *server.DBConn, regid uint) (*PollMessage, err var poll_msg *PollMessage switch msgtype { case POLL_LOW_CREDIT: - poll_msg = &PollMessage{Msgid:msgid, Msg:"Credit balance low."} + poll_msg = &PollMessage{} + poll_msg.Msgid = msgid + poll_msg.Msg = "Credit balance low." case POLL_TRANSFER_REQUEST: - poll_msg, err = getPollTransferObject(db, msgid) + poll_msg, err = p.getPollTransferObject(msgid) if err != nil { return poll_msg, err } default: - poll_msg = &PollMessage{Msgid:msgid, Msg:"unsupported"} + poll_msg = &PollMessage{} + poll_msg.Msgid = msgid + poll_msg.Msg = "unsupported" } poll_msg.MsgType = msgtype poll_msg.QDate = crdate @@ -89,4 +114,3 @@ func MarkMessageRead(db *server.DBConn, regid uint, msgid uint64) error { _, err := db.Exec(query, msgid, regid) return err } - diff --git a/registry/epp/epp.go b/registry/epp/epp.go index 1732764..78c00dd 100644 --- a/registry/epp/epp.go +++ b/registry/epp/epp.go @@ -34,6 +34,23 @@ func (e *EPPContext) ResolveErrorMsg(db *server.DBConn, epp_result *EPPResult, l } } +func (e *EPPContext) FillMsgQ(epp_result *EPPResult) error { + if e.session == nil { + return nil + } + /* could already be filled */ + if epp_result.MsgQ != nil { + return nil + } + poll_msg, err := get_poll_msg(e) + if err != nil { + return err + } + epp_result.MsgQ = &poll_msg.MsgQ + return nil +} + + func (e *EPPContext) SetLogger(logger server.Logger) { e.logger = logger } @@ -177,6 +194,9 @@ func (ctx *EPPContext) ExecuteEPPCommand(ctx_ context.Context, cmd *xml.XMLComma epp_result = &EPPResult{CmdType:EPP_UNKNOWN_CMD, RetCode:EPP_UNKNOWN_ERR} } epp_result.CmdType = cmd.CmdType + if err := ctx.FillMsgQ(epp_result); err != nil { + ctx.logger.Error(err) + } ctx.ResolveErrorMsg(ctx.dbconn, epp_result, Lang) return epp_result diff --git a/registry/epp/epp_poll.go b/registry/epp/epp_poll.go index b0d5216..f734a4f 100644 --- a/registry/epp/epp_poll.go +++ b/registry/epp/epp_poll.go @@ -1,33 +1,50 @@ package epp import ( -// "registry/xml" "strconv" "registry/epp/dbreg" . "registry/epp/eppcom" ) -func epp_poll_req_impl(ctx *EPPContext) *EPPResult { - ctx.logger.Info("Poll req") +func get_poll_msg(ctx *EPPContext) (*PollMessage, error) { + var poll_msg *PollMessage - count, err := dbreg.GetPollMessageCount(ctx.dbconn, ctx.session.Regid) + ctx.logger.Trace(ctx.session.Regid) + poll := dbreg.NewPollMsg(ctx.dbconn, ctx.session.Regid) + count, err := poll.GetPollMessageCount() if err != nil { - ctx.logger.Error(err) - return &EPPResult{RetCode:EPP_FAILED} + return poll_msg, err } if count == 0 { - return &EPPResult{RetCode:EPP_POLL_NO_MSG} + poll_msg = &PollMessage{} + poll_msg.Count = count + return poll_msg, nil } - poll_msg, err := dbreg.GetFirstUnreadPollMessage(ctx.dbconn, ctx.session.Regid) + poll_msg, err = poll.SetExtended(true).GetFirstUnreadPollMessage() + if err != nil { + return poll_msg, err + } + poll_msg.Count = count + + return poll_msg, nil +} + +func epp_poll_req_impl(ctx *EPPContext) *EPPResult { + ctx.logger.Info("Poll req") + + poll_msg, err := get_poll_msg(ctx) if err != nil { ctx.logger.Error(err) return &EPPResult{RetCode:EPP_FAILED} } - poll_msg.Count = count + + if poll_msg.Count == 0 { + return &EPPResult{RetCode:EPP_POLL_NO_MSG} + } var res = EPPResult{RetCode:EPP_POLL_ACK_MSG} - res.Content = poll_msg + res.Content = poll_msg.Content return &res } @@ -46,6 +63,5 @@ func epp_poll_ack_impl(ctx *EPPContext, msgid string) *EPPResult { } var res = EPPResult{RetCode:EPP_OK} -// res.Content = host_data return &res } diff --git a/registry/epp/eppcom/eppstruct.go b/registry/epp/eppcom/eppstruct.go index 57520e0..4ce8e8f 100644 --- a/registry/epp/eppcom/eppstruct.go +++ b/registry/epp/eppcom/eppstruct.go @@ -75,6 +75,19 @@ type SecDNSUpdate struct { RemAll bool } +type MsgQ struct { + Msgid uint + Msg string + Count uint + MsgType uint + QDate pgtype.Timestamp /* when poll message was created */ +} + +type PollMessage struct { + MsgQ + Content interface{} +} + /* main structure returned by ExecuteEPPCommand */ type EPPResult struct { CmdType int @@ -86,6 +99,7 @@ type EPPResult struct { Content interface{} // EPP Extensions Ext []EPPExt + MsgQ *MsgQ } type CheckResult struct { @@ -229,12 +243,3 @@ type CreateDomainResult struct { CreateObjectResult Exdate pgtype.Timestamp } - -type PollMessage struct { - MsgType uint - Msgid uint - Msg string - Count uint - QDate pgtype.Timestamp /* when poll message was created */ - Content interface{} -} diff --git a/registry/tests/epptests/epp_domain_test.go b/registry/tests/epptests/epp_domain_test.go index 0e9ee9f..2dffa4e 100644 --- a/registry/tests/epptests/epp_domain_test.go +++ b/registry/tests/epptests/epp_domain_test.go @@ -333,7 +333,6 @@ func TestEPPDomainTransfer(t *testing.T) { /* access to a second registrar should not be allowed without a transfer */ _ = infoDomain(t, eppc, test_domain, EPP_AUTHORIZATION_ERR, sessionid2) - _ = infoContact(t, eppc, test_contact, EPP_AUTHORIZATION_ERR, sessionid2) transferDomain(t, eppc, test_domain, reg_handle2, TR_REQUEST, EPP_OK, sessionid) transferDomain(t, eppc, test_domain, reg_handle2, TR_QUERY, EPP_OK, sessionid) @@ -351,11 +350,11 @@ func TestEPPDomainTransfer(t *testing.T) { if epp_res.RetCode != EPP_POLL_ACK_MSG { t.Error("should be ", EPP_POLL_ACK_MSG, epp_res.RetCode) } - poll_msg, ok := epp_res.Content.(*PollMessage) + _, ok := epp_res.Content.(*TransferRequestObject) if !ok { t.Error("should be ok") } - pollAck(t, eppc, poll_msg.Msgid, EPP_OK, sessionid2) + pollAck(t, eppc, epp_res.MsgQ.Msgid, EPP_OK, sessionid2) transferDomain(t, eppc, test_domain, "", TR_REJECT, EPP_OK, sessionid2) @@ -409,6 +408,9 @@ func TestEPPDomainTransfer2(t *testing.T) { createHost(t, eppc, test_host1, []string{}, EPP_OK, sessionid) createHost(t, eppc, test_host2, []string{}, EPP_OK, sessionid) + /* access to a second registrar should not be allowed without a transfer */ + _ = infoContact(t, eppc, test_contact, EPP_AUTHORIZATION_ERR, sessionid2) + createDomain(t, eppc, test_domain, test_contact, EPP_OK, sessionid) updateDomainHosts(t, eppc, test_domain, []string{test_host1, test_host2}, []string{}, EPP_OK, sessionid) diff --git a/registry/tests/epptests/epp_test.go b/registry/tests/epptests/epp_test.go index 00e39f5..41f7af0 100644 --- a/registry/tests/epptests/epp_test.go +++ b/registry/tests/epptests/epp_test.go @@ -193,11 +193,10 @@ func TestEPPPoll(t *testing.T) { if epp_res.RetCode != EPP_POLL_ACK_MSG { t.Error("should be ", EPP_POLL_ACK_MSG, epp_res.RetCode) } - poll_msg, ok := epp_res.Content.(*PollMessage) - if !ok { + if epp_res.Content == nil { t.Error("should be ok") } - pollAck(t, eppc, poll_msg.Msgid, EPP_OK, sessionid) + pollAck(t, eppc, epp_res.MsgQ.Msgid, EPP_OK, sessionid) } func infoContact(t *testing.T, eppc *epp.EPPContext, name string, retcode int, sessionid uint64) *InfoContactData { diff --git a/registry/xml/xml_gen.go b/registry/xml/xml_gen.go index 66a5552..849d46a 100644 --- a/registry/xml/xml_gen.go +++ b/registry/xml/xml_gen.go @@ -3,6 +3,7 @@ package xml import ( "time" "bytes" + "strings" . "registry/epp/eppcom" "encoding/xml" "github.com/kpango/glg" @@ -143,8 +144,8 @@ func CreateDomainResponse(response *EPPResult) *ResDataS { return &ResDataS{Obj:domain} } -func TransferDomainResponse(response *EPPResult) *ResDataS { - tr_data, ok := response.Content.(*TransferRequestObject) +func TransferDomainResponse(content interface{}) *ResDataS { + tr_data, ok := content.(*TransferRequestObject) if !ok { glg.Error("conversion error") return nil @@ -163,6 +164,14 @@ func TransferDomainResponse(response *EPPResult) *ResDataS { return &ResDataS{Obj:trn} } +func get_ipversion(ipaddr string) string { + if strings.Contains(ipaddr, ":") { + return "v6" + } else { + return "v4" + } +} + func HostResponse(response *EPPResult) *ResDataS { host_data, ok := response.Content.(*InfoHostData) if !ok { @@ -184,7 +193,9 @@ func HostResponse(response *EPPResult) *ResDataS { for _,v := range host_data.States { host.States = append(host.States, ObjectState{Val:v}) } - host.Addrs = append(host.Addrs, host_data.Addrs...) + for _, ipaddr := range host_data.Addrs { + host.Addrs = append(host.Addrs, IPAddr{IPAddr:ipaddr, IPVer:get_ipversion(ipaddr)}) + } return &ResDataS{Obj:host} } @@ -272,13 +283,8 @@ func CreateContactResponse(response *EPPResult) *ResDataS { return &ResDataS{Obj:contact} } -func PollReqResponse(response *EPPResult) *MsgQ { - poll_msg, ok := response.Content.(*PollMessage) - if !ok { - glg.Error("conversion error") - return nil - } - msg_q := &MsgQ{ +func PollReqResponse(poll_msg *MsgQ) *MsgQResponse { + msg_q := &MsgQResponse{ Count:poll_msg.Count, MsgId:poll_msg.Msgid, Msg:poll_msg.Msg, @@ -287,6 +293,16 @@ func PollReqResponse(response *EPPResult) *MsgQ { return msg_q } +func PollResponse(response *EPPResult) *ResDataS { + if response.MsgQ == nil { + return nil + } + if response.MsgQ.MsgType == 22 { + return TransferDomainResponse(response.Content) + } + return nil +} + func RegistrarResponse(response *EPPResult) *ResDataS { registrar_data, ok := response.Content.(*InfoRegistrarData) if !ok { @@ -310,7 +326,9 @@ func RegistrarResponse(response *EPPResult) *ResDataS { UpDate:FormatDatePG(registrar_data.Update_time), } - registrar.Addrs = append(registrar.Addrs, registrar_data.Addrs...) + for _, ipaddr := range registrar_data.Addrs { + registrar.Addrs = append(registrar.Addrs, IPAddr{IPAddr:ipaddr, IPVer:get_ipversion(ipaddr)}) + } return &ResDataS{Obj:registrar} } @@ -326,7 +344,7 @@ func GenerateResponse(response *EPPResult, clTRID string, svTRID string) string } else { resp.Result.Msg = response.Msg } - if resp.Result.Code != 1000 { + if resp.Result.Code != 1000 && resp.Result.Code != 1301 { if len(response.Errors) > 0 { for _,v := range response.Errors { resp.Result.ExtValue = append(resp.Result.ExtValue, ExtValueS{Reason:v}) @@ -358,7 +376,10 @@ func GenerateResponse(response *EPPResult, clTRID string, svTRID string) string resp.ResData = CreateContactResponse(response) case EPP_TRANSFER_DOMAIN: - resp.ResData = TransferDomainResponse(response) + resp.ResData = TransferDomainResponse(response.Content) + + case EPP_POLL_REQ: + resp.ResData = PollResponse(response) } } @@ -371,10 +392,8 @@ func GenerateResponse(response *EPPResult, clTRID string, svTRID string) string } } - if response.CmdType == EPP_POLL_REQ { - if response.Content != nil { - resp.MsgQ = PollReqResponse(response) - } + if response.MsgQ != nil { + resp.MsgQ = PollReqResponse(response.MsgQ) } resp.TrID.ClTRID = clTRID resp.TrID.SvTRID = svTRID diff --git a/registry/xml/xml_gen_defs.go b/registry/xml/xml_gen_defs.go index 532ce83..6060777 100644 --- a/registry/xml/xml_gen_defs.go +++ b/registry/xml/xml_gen_defs.go @@ -64,6 +64,11 @@ type Domain struct { TrDate string `xml:"trDate,omitempty"` } +type IPAddr struct { + IPAddr string `xml:",chardata"` + IPVer string `xml:"ip,attr,omitempty"` +} + type Host struct { XMLName xml.Name `xml:"host:infData"` XMLNSDom string `xml:"xmlns:host,attr"` @@ -71,7 +76,7 @@ type Host struct { Name string `xml:"name"` Roid string `xml:"roid"` States []ObjectState `xml:"status"` - Addrs []string `xml:"addr,omitempty"` + Addrs []IPAddr `xml:"addr,omitempty"` ClID string `xml:"clID"` CrID string `xml:"crID"` CrDate string `xml:"crDate"` @@ -158,7 +163,7 @@ type Registrar struct { Email []string `xml:"email,omitempty"` WWW string `xml:"www,omitempty"` Whois string `xml:"whois,omitempty"` - Addrs []string `xml:"addr,omitempty"` + Addrs []IPAddr `xml:"addr,omitempty"` UpDate string `xml:"upDate,omitempty"` } @@ -249,7 +254,7 @@ type TransferResponse struct { AcDate string `xml:"acDate"` } -type MsgQ struct { +type MsgQResponse struct { XMLName xml.Name `xml:"msgQ"` Count uint `xml:"count,attr"` MsgId uint `xml:"id,attr"`